Rename TypeRecording...Stub into ...Stub.
There is no need for this long name. Review URL: http://codereview.chromium.org/7063017 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8031 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
24222bdb57
commit
5552dbccdd
@ -1707,14 +1707,13 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingUnaryOpStub(int key,
|
Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
|
||||||
TRUnaryOpIC::TypeInfo type_info) {
|
UnaryOpStub stub(key, type_info);
|
||||||
TypeRecordingUnaryOpStub stub(key, type_info);
|
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingUnaryOpStub::GetName() {
|
const char* UnaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -1728,34 +1727,34 @@ const char* TypeRecordingUnaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingUnaryOpStub_%s_%s_%s",
|
"UnaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) {
|
void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operand_type_) {
|
switch (operand_type_) {
|
||||||
case TRUnaryOpIC::UNINITIALIZED:
|
case UnaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::SMI:
|
case UnaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::HEAP_NUMBER:
|
case UnaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::GENERIC:
|
case UnaryOpIC::GENERIC:
|
||||||
GenerateGenericStub(masm);
|
GenerateGenericStub(masm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
// Prepare to push argument.
|
// Prepare to push argument.
|
||||||
__ mov(r3, Operand(r0));
|
__ mov(r3, Operand(r0));
|
||||||
|
|
||||||
@ -1768,7 +1767,7 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
__ Push(r3, r2, r1, r0);
|
__ Push(r3, r2, r1, r0);
|
||||||
|
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kUnaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
4,
|
4,
|
||||||
1);
|
1);
|
||||||
@ -1776,7 +1775,7 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateSmiStubSub(masm);
|
GenerateSmiStubSub(masm);
|
||||||
@ -1790,7 +1789,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1799,7 +1798,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi;
|
Label non_smi;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1807,9 +1806,9 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
||||||
Label* non_smi,
|
Label* non_smi,
|
||||||
Label* slow) {
|
Label* slow) {
|
||||||
__ JumpIfNotSmi(r0, non_smi);
|
__ JumpIfNotSmi(r0, non_smi);
|
||||||
|
|
||||||
// The result of negating zero or the smallest negative smi is not a smi.
|
// The result of negating zero or the smallest negative smi is not a smi.
|
||||||
@ -1822,8 +1821,8 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
||||||
Label* non_smi) {
|
Label* non_smi) {
|
||||||
__ JumpIfNotSmi(r0, non_smi);
|
__ JumpIfNotSmi(r0, non_smi);
|
||||||
|
|
||||||
// Flip bits and revert inverted smi-tag.
|
// Flip bits and revert inverted smi-tag.
|
||||||
@ -1834,7 +1833,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateHeapNumberStubSub(masm);
|
GenerateHeapNumberStubSub(masm);
|
||||||
@ -1848,7 +1847,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow, call_builtin;
|
Label non_smi, slow, call_builtin;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
|
GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1860,8 +1859,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1870,8 +1868,8 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
|||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
||||||
Label* slow) {
|
Label* slow) {
|
||||||
EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
|
EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
|
||||||
// r0 is a heap number. Get a new heap number in r1.
|
// r0 is a heap number. Get a new heap number in r1.
|
||||||
if (mode_ == UNARY_OVERWRITE) {
|
if (mode_ == UNARY_OVERWRITE) {
|
||||||
@ -1903,7 +1901,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
void UnaryOpStub::GenerateHeapNumberCodeBitNot(
|
||||||
MacroAssembler* masm, Label* slow) {
|
MacroAssembler* masm, Label* slow) {
|
||||||
EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
|
EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
|
||||||
// Convert the heap number is r0 to an untagged integer in r1.
|
// Convert the heap number is r0 to an untagged integer in r1.
|
||||||
@ -1954,7 +1952,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateGenericStubSub(masm);
|
GenerateGenericStubSub(masm);
|
||||||
@ -1968,7 +1966,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1978,7 +1976,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1988,8 +1986,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
// Handle the slow case by jumping to the JavaScript builtin.
|
// Handle the slow case by jumping to the JavaScript builtin.
|
||||||
__ push(r0);
|
__ push(r0);
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
@ -2005,15 +2002,15 @@ void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
|
Handle<Code> GetBinaryOpStub(int key,
|
||||||
TRBinaryOpIC::TypeInfo type_info,
|
BinaryOpIC::TypeInfo type_info,
|
||||||
TRBinaryOpIC::TypeInfo result_type_info) {
|
BinaryOpIC::TypeInfo result_type_info) {
|
||||||
TypeRecordingBinaryOpStub stub(key, type_info, result_type_info);
|
BinaryOpStub stub(key, type_info, result_type_info);
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
Label get_result;
|
Label get_result;
|
||||||
|
|
||||||
__ Push(r1, r0);
|
__ Push(r1, r0);
|
||||||
@ -2024,43 +2021,43 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
__ Push(r2, r1, r0);
|
__ Push(r2, r1, r0);
|
||||||
|
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
5,
|
5,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
||||||
MacroAssembler* masm) {
|
MacroAssembler* masm) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
void BinaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operands_type_) {
|
switch (operands_type_) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
GenerateInt32Stub(masm);
|
GenerateInt32Stub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::ODDBALL:
|
case BinaryOpIC::ODDBALL:
|
||||||
GenerateOddballStub(masm);
|
GenerateOddballStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::BOTH_STRING:
|
case BinaryOpIC::BOTH_STRING:
|
||||||
GenerateBothStringStub(masm);
|
GenerateBothStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::STRING:
|
case BinaryOpIC::STRING:
|
||||||
GenerateStringStub(masm);
|
GenerateStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::GENERIC:
|
case BinaryOpIC::GENERIC:
|
||||||
GenerateGeneric(masm);
|
GenerateGeneric(masm);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2069,7 +2066,7 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingBinaryOpStub::GetName() {
|
const char* BinaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -2085,16 +2082,15 @@ const char* TypeRecordingBinaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingBinaryOpStub_%s_%s_%s",
|
"BinaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
|
void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
Register scratch1 = r7;
|
Register scratch1 = r7;
|
||||||
@ -2219,10 +2215,10 @@ void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
||||||
bool smi_operands,
|
bool smi_operands,
|
||||||
Label* not_numbers,
|
Label* not_numbers,
|
||||||
Label* gc_required) {
|
Label* gc_required) {
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
Register scratch1 = r7;
|
Register scratch1 = r7;
|
||||||
@ -2433,7 +2429,8 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|||||||
// generated. If the result is not a smi and heap number allocation is not
|
// generated. If the result is not a smi and heap number allocation is not
|
||||||
// requested the code falls through. If number allocation is requested but a
|
// requested the code falls through. If number allocation is requested but a
|
||||||
// heap number cannot be allocated the code jumps to the lable gc_required.
|
// heap number cannot be allocated the code jumps to the lable gc_required.
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
void BinaryOpStub::GenerateSmiCode(
|
||||||
|
MacroAssembler* masm,
|
||||||
Label* use_runtime,
|
Label* use_runtime,
|
||||||
Label* gc_required,
|
Label* gc_required,
|
||||||
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
||||||
@ -2462,11 +2459,11 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
Label not_smis, call_runtime;
|
Label not_smis, call_runtime;
|
||||||
|
|
||||||
if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
|
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
|
||||||
result_type_ == TRBinaryOpIC::SMI) {
|
result_type_ == BinaryOpIC::SMI) {
|
||||||
// Only allow smi results.
|
// Only allow smi results.
|
||||||
GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
|
||||||
} else {
|
} else {
|
||||||
@ -2487,19 +2484,19 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::STRING);
|
ASSERT(operands_type_ == BinaryOpIC::STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
// Try to add arguments as strings, otherwise, transition to the generic
|
// Try to add arguments as strings, otherwise, transition to the generic
|
||||||
// TRBinaryOpIC type.
|
// BinaryOpIC type.
|
||||||
GenerateAddStrings(masm);
|
GenerateAddStrings(masm);
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING);
|
ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
// If both arguments are strings, call the string add stub.
|
// If both arguments are strings, call the string add stub.
|
||||||
// Otherwise, do a transition.
|
// Otherwise, do a transition.
|
||||||
@ -2527,8 +2524,8 @@ void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::INT32);
|
ASSERT(operands_type_ == BinaryOpIC::INT32);
|
||||||
|
|
||||||
Register left = r1;
|
Register left = r1;
|
||||||
Register right = r0;
|
Register right = r0;
|
||||||
@ -2625,7 +2622,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
scratch1,
|
scratch1,
|
||||||
scratch2);
|
scratch2);
|
||||||
|
|
||||||
if (result_type_ <= TRBinaryOpIC::INT32) {
|
if (result_type_ <= BinaryOpIC::INT32) {
|
||||||
// If the ne condition is set, result does
|
// If the ne condition is set, result does
|
||||||
// not fit in a 32-bit integer.
|
// not fit in a 32-bit integer.
|
||||||
__ b(ne, &transition);
|
__ b(ne, &transition);
|
||||||
@ -2652,8 +2649,8 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
// DIV just falls through to allocating a heap number.
|
// DIV just falls through to allocating a heap number.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result_type_ >= (op_ == Token::DIV) ? TRBinaryOpIC::HEAP_NUMBER
|
if (result_type_ >= (op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
|
||||||
: TRBinaryOpIC::INT32) {
|
: BinaryOpIC::INT32) {
|
||||||
__ bind(&return_heap_number);
|
__ bind(&return_heap_number);
|
||||||
// We are using vfp registers so r5 is available.
|
// We are using vfp registers so r5 is available.
|
||||||
heap_number_result = r5;
|
heap_number_result = r5;
|
||||||
@ -2762,12 +2759,13 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
// The non vfp3 code does not support this special case, so jump to
|
// The non vfp3 code does not support this special case, so jump to
|
||||||
// runtime if we don't support it.
|
// runtime if we don't support it.
|
||||||
if (CpuFeatures::IsSupported(VFP3)) {
|
if (CpuFeatures::IsSupported(VFP3)) {
|
||||||
__ b(mi,
|
__ b(mi, (result_type_ <= BinaryOpIC::INT32)
|
||||||
(result_type_ <= TRBinaryOpIC::INT32) ? &transition
|
? &transition
|
||||||
: &return_heap_number);
|
: &return_heap_number);
|
||||||
} else {
|
} else {
|
||||||
__ b(mi, (result_type_ <= TRBinaryOpIC::INT32) ? &transition
|
__ b(mi, (result_type_ <= BinaryOpIC::INT32)
|
||||||
: &call_runtime);
|
? &transition
|
||||||
|
: &call_runtime);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Token::SHL:
|
case Token::SHL:
|
||||||
@ -2837,7 +2835,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
|
|
||||||
if (op_ == Token::ADD) {
|
if (op_ == Token::ADD) {
|
||||||
@ -2870,7 +2868,7 @@ void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
|
GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
|
||||||
|
|
||||||
@ -2879,7 +2877,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
||||||
Label call_runtime, call_string_add_or_runtime;
|
Label call_runtime, call_string_add_or_runtime;
|
||||||
|
|
||||||
GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
||||||
@ -2896,7 +2894,7 @@ void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
Label left_not_string, call_runtime;
|
Label left_not_string, call_runtime;
|
||||||
|
|
||||||
@ -2927,7 +2925,7 @@ void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
|
||||||
GenerateRegisterArgsPush(masm);
|
GenerateRegisterArgsPush(masm);
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::ADD:
|
case Token::ADD:
|
||||||
@ -2969,14 +2967,12 @@ void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
void BinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
|
||||||
MacroAssembler* masm,
|
Register result,
|
||||||
Register result,
|
Register heap_number_map,
|
||||||
Register heap_number_map,
|
Register scratch1,
|
||||||
Register scratch1,
|
Register scratch2,
|
||||||
Register scratch2,
|
Label* gc_required) {
|
||||||
Label* gc_required) {
|
|
||||||
|
|
||||||
// Code below will scratch result if allocation fails. To keep both arguments
|
// Code below will scratch result if allocation fails. To keep both arguments
|
||||||
// intact for the runtime call result cannot be one of these.
|
// intact for the runtime call result cannot be one of these.
|
||||||
ASSERT(!result.is(r0) && !result.is(r1));
|
ASSERT(!result.is(r0) && !result.is(r1));
|
||||||
@ -3003,7 +2999,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
||||||
__ Push(r1, r0);
|
__ Push(r1, r0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,18 +71,18 @@ class ToBooleanStub: public CodeStub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingUnaryOpStub: public CodeStub {
|
class UnaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingUnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
UnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operand_type_(TRUnaryOpIC::UNINITIALIZED),
|
operand_type_(UnaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingUnaryOpStub(
|
UnaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRUnaryOpIC::TypeInfo operand_type)
|
UnaryOpIC::TypeInfo operand_type)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
operand_type_(operand_type),
|
operand_type_(operand_type),
|
||||||
@ -94,7 +94,7 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
UnaryOverwriteMode mode_;
|
UnaryOverwriteMode mode_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRUnaryOpIC::TypeInfo operand_type_;
|
UnaryOpIC::TypeInfo operand_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -102,20 +102,20 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingUnaryOpStub %d (op %s), "
|
PrintF("UnaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
||||||
class OpBits: public BitField<Token::Value, 1, 7> {};
|
class OpBits: public BitField<Token::Value, 1, 7> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRUnaryOpIC::TypeInfo, 8, 3> {};
|
class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingUnaryOp; }
|
Major MajorKey() { return UnaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return ModeBits::encode(mode_)
|
return ModeBits::encode(mode_)
|
||||||
| OpBits::encode(op_)
|
| OpBits::encode(op_)
|
||||||
@ -145,34 +145,34 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
||||||
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_UNARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRUnaryOpIC::ToState(operand_type_);
|
return UnaryOpIC::ToState(operand_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_unary_op_type(operand_type_);
|
code->set_unary_op_type(operand_type_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingBinaryOpStub: public CodeStub {
|
class BinaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
|
BinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operands_type_(TRBinaryOpIC::UNINITIALIZED),
|
operands_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
result_type_(TRBinaryOpIC::UNINITIALIZED),
|
result_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
use_vfp3_ = CpuFeatures::IsSupported(VFP3);
|
use_vfp3_ = CpuFeatures::IsSupported(VFP3);
|
||||||
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub(
|
BinaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRBinaryOpIC::TypeInfo operands_type,
|
BinaryOpIC::TypeInfo operands_type,
|
||||||
TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
|
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
use_vfp3_(VFP3Bits::decode(key)),
|
use_vfp3_(VFP3Bits::decode(key)),
|
||||||
@ -191,8 +191,8 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
bool use_vfp3_;
|
bool use_vfp3_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRBinaryOpIC::TypeInfo operands_type_;
|
BinaryOpIC::TypeInfo operands_type_;
|
||||||
TRBinaryOpIC::TypeInfo result_type_;
|
BinaryOpIC::TypeInfo result_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -200,12 +200,12 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingBinaryOpStub %d (op %s), "
|
PrintF("BinaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -213,10 +213,10 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
||||||
class OpBits: public BitField<Token::Value, 2, 7> {};
|
class OpBits: public BitField<Token::Value, 2, 7> {};
|
||||||
class VFP3Bits: public BitField<bool, 9, 1> {};
|
class VFP3Bits: public BitField<bool, 9, 1> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 10, 3> {};
|
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
|
||||||
class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 13, 3> {};
|
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingBinaryOp; }
|
Major MajorKey() { return BinaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return OpBits::encode(op_)
|
return OpBits::encode(op_)
|
||||||
| ModeBits::encode(mode_)
|
| ModeBits::encode(mode_)
|
||||||
@ -259,15 +259,15 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
void GenerateTypeTransition(MacroAssembler* masm);
|
void GenerateTypeTransition(MacroAssembler* masm);
|
||||||
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRBinaryOpIC::ToState(operands_type_);
|
return BinaryOpIC::ToState(operands_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_binary_op_type(operands_type_);
|
code->set_binary_op_type(operands_type_);
|
||||||
code->set_type_recording_binary_op_result_type(result_type_);
|
code->set_binary_op_result_type(result_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CodeGenerator;
|
friend class CodeGenerator;
|
||||||
|
@ -1717,14 +1717,14 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
patch_site.EmitJumpIfSmi(scratch1, &smi_case);
|
patch_site.EmitJumpIfSmi(scratch1, &smi_case);
|
||||||
|
|
||||||
__ bind(&stub_call);
|
__ bind(&stub_call);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
||||||
__ jmp(&done);
|
__ jmp(&done);
|
||||||
|
|
||||||
__ bind(&smi_case);
|
__ bind(&smi_case);
|
||||||
// Smi case. This code works the same way as the smi-smi case in the type
|
// Smi case. This code works the same way as the smi-smi case in the type
|
||||||
// recording binary operation stub, see
|
// recording binary operation stub, see
|
||||||
// TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments.
|
// BinaryOpStub::GenerateSmiSmiOperation for comments.
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Token::SAR:
|
case Token::SAR:
|
||||||
__ b(&stub_call);
|
__ b(&stub_call);
|
||||||
@ -1798,7 +1798,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
|||||||
Token::Value op,
|
Token::Value op,
|
||||||
OverwriteMode mode) {
|
OverwriteMode mode) {
|
||||||
__ pop(r1);
|
__ pop(r1);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
||||||
context()->Plug(r0);
|
context()->Plug(r0);
|
||||||
}
|
}
|
||||||
@ -3790,8 +3790,8 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
|||||||
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
||||||
UnaryOverwriteMode overwrite =
|
UnaryOverwriteMode overwrite =
|
||||||
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
||||||
TypeRecordingUnaryOpStub stub(expr->op(), overwrite);
|
UnaryOpStub stub(expr->op(), overwrite);
|
||||||
// TypeRecordingGenericUnaryOpStub expects the argument to be in the
|
// UnaryOpStub expects the argument to be in the
|
||||||
// accumulator register r0.
|
// accumulator register r0.
|
||||||
VisitForAccumulatorValue(expr->expression());
|
VisitForAccumulatorValue(expr->expression());
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
@ -3912,7 +3912,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
// Record position before stub call.
|
// Record position before stub call.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE);
|
BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
|
|
||||||
|
@ -1093,7 +1093,7 @@ void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
|
|||||||
__ mov(r0, right);
|
__ mov(r0, right);
|
||||||
__ mov(r1, left);
|
__ mov(r1, left);
|
||||||
}
|
}
|
||||||
TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT);
|
BinaryOpStub stub(op, OVERWRITE_LEFT);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
|
RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
|
||||||
0,
|
0,
|
||||||
@ -1399,7 +1399,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
|||||||
ASSERT(ToRegister(instr->InputAt(1)).is(r0));
|
ASSERT(ToRegister(instr->InputAt(1)).is(r0));
|
||||||
ASSERT(ToRegister(instr->result()).is(r0));
|
ASSERT(ToRegister(instr->result()).is(r0));
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
BinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ namespace internal {
|
|||||||
// as only the stubs up to and including Instanceof allows nested stub calls.
|
// as only the stubs up to and including Instanceof allows nested stub calls.
|
||||||
#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
|
#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
|
||||||
V(CallFunction) \
|
V(CallFunction) \
|
||||||
V(TypeRecordingUnaryOp) \
|
V(UnaryOp) \
|
||||||
V(TypeRecordingBinaryOp) \
|
V(BinaryOp) \
|
||||||
V(StringAdd) \
|
V(StringAdd) \
|
||||||
V(SubString) \
|
V(SubString) \
|
||||||
V(StringCompare) \
|
V(StringCompare) \
|
||||||
@ -55,7 +55,6 @@ namespace internal {
|
|||||||
V(FastNewClosure) \
|
V(FastNewClosure) \
|
||||||
V(FastNewContext) \
|
V(FastNewContext) \
|
||||||
V(FastCloneShallowArray) \
|
V(FastCloneShallowArray) \
|
||||||
V(GenericUnaryOp) \
|
|
||||||
V(RevertToNumber) \
|
V(RevertToNumber) \
|
||||||
V(ToBoolean) \
|
V(ToBoolean) \
|
||||||
V(ToNumber) \
|
V(ToNumber) \
|
||||||
@ -170,10 +169,10 @@ class CodeStub BASE_EMBEDDED {
|
|||||||
// lazily generated function should be fully optimized or not.
|
// lazily generated function should be fully optimized or not.
|
||||||
virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
|
virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
|
||||||
|
|
||||||
// TypeRecordingBinaryOpStub needs to override this.
|
// BinaryOpStub needs to override this.
|
||||||
virtual int GetCodeKind();
|
virtual int GetCodeKind();
|
||||||
|
|
||||||
// TypeRecordingBinaryOpStub needs to override this.
|
// BinaryOpStub needs to override this.
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return UNINITIALIZED;
|
return UNINITIALIZED;
|
||||||
}
|
}
|
||||||
|
@ -167,8 +167,8 @@ void BreakLocationIterator::Next() {
|
|||||||
Address target = original_rinfo()->target_address();
|
Address target = original_rinfo()->target_address();
|
||||||
Code* code = Code::GetCodeFromTargetAddress(target);
|
Code* code = Code::GetCodeFromTargetAddress(target);
|
||||||
if ((code->is_inline_cache_stub() &&
|
if ((code->is_inline_cache_stub() &&
|
||||||
!code->is_type_recording_binary_op_stub() &&
|
!code->is_binary_op_stub() &&
|
||||||
!code->is_type_recording_unary_op_stub() &&
|
!code->is_unary_op_stub() &&
|
||||||
!code->is_compare_ic_stub()) ||
|
!code->is_compare_ic_stub()) ||
|
||||||
RelocInfo::IsConstructCall(rmode())) {
|
RelocInfo::IsConstructCall(rmode())) {
|
||||||
break_point_++;
|
break_point_++;
|
||||||
|
@ -517,14 +517,13 @@ static void IntegerConvert(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingUnaryOpStub(int key,
|
Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
|
||||||
TRUnaryOpIC::TypeInfo type_info) {
|
UnaryOpStub stub(key, type_info);
|
||||||
TypeRecordingUnaryOpStub stub(key, type_info);
|
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingUnaryOpStub::GetName() {
|
const char* UnaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -538,34 +537,34 @@ const char* TypeRecordingUnaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingUnaryOpStub_%s_%s_%s",
|
"UnaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) {
|
void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operand_type_) {
|
switch (operand_type_) {
|
||||||
case TRUnaryOpIC::UNINITIALIZED:
|
case UnaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::SMI:
|
case UnaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::HEAP_NUMBER:
|
case UnaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::GENERIC:
|
case UnaryOpIC::GENERIC:
|
||||||
GenerateGenericStub(masm);
|
GenerateGenericStub(masm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
__ pop(ecx); // Save return address.
|
__ pop(ecx); // Save return address.
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
// the argument is now on top.
|
// the argument is now on top.
|
||||||
@ -580,15 +579,13 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
// Patch the caller to an appropriate specialized stub and return the
|
// Patch the caller to an appropriate specialized stub and return the
|
||||||
// operation result to the caller of the stub.
|
// operation result to the caller of the stub.
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kUnaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()), 4, 1);
|
||||||
4,
|
|
||||||
1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateSmiStubSub(masm);
|
GenerateSmiStubSub(masm);
|
||||||
@ -602,7 +599,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, undo, slow;
|
Label non_smi, undo, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &undo, &slow,
|
GenerateSmiCodeSub(masm, &non_smi, &undo, &slow,
|
||||||
Label::kNear, Label::kNear, Label::kNear);
|
Label::kNear, Label::kNear, Label::kNear);
|
||||||
@ -614,7 +611,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi;
|
Label non_smi;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -622,13 +619,13 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
||||||
Label* non_smi,
|
Label* non_smi,
|
||||||
Label* undo,
|
Label* undo,
|
||||||
Label* slow,
|
Label* slow,
|
||||||
Label::Distance non_smi_near,
|
Label::Distance non_smi_near,
|
||||||
Label::Distance undo_near,
|
Label::Distance undo_near,
|
||||||
Label::Distance slow_near) {
|
Label::Distance slow_near) {
|
||||||
// Check whether the value is a smi.
|
// Check whether the value is a smi.
|
||||||
__ test(eax, Immediate(kSmiTagMask));
|
__ test(eax, Immediate(kSmiTagMask));
|
||||||
__ j(not_zero, non_smi, non_smi_near);
|
__ j(not_zero, non_smi, non_smi_near);
|
||||||
@ -646,7 +643,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(
|
void UnaryOpStub::GenerateSmiCodeBitNot(
|
||||||
MacroAssembler* masm,
|
MacroAssembler* masm,
|
||||||
Label* non_smi,
|
Label* non_smi,
|
||||||
Label::Distance non_smi_near) {
|
Label::Distance non_smi_near) {
|
||||||
@ -661,13 +658,13 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) {
|
||||||
__ mov(eax, Operand(edx));
|
__ mov(eax, Operand(edx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateHeapNumberStubSub(masm);
|
GenerateHeapNumberStubSub(masm);
|
||||||
@ -681,7 +678,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, undo, slow, call_builtin;
|
Label non_smi, undo, slow, call_builtin;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear);
|
GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -695,7 +692,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
void UnaryOpStub::GenerateHeapNumberStubBitNot(
|
||||||
MacroAssembler* masm) {
|
MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||||
@ -706,8 +703,8 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
||||||
Label* slow) {
|
Label* slow) {
|
||||||
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
|
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
__ cmp(edx, masm->isolate()->factory()->heap_number_map());
|
__ cmp(edx, masm->isolate()->factory()->heap_number_map());
|
||||||
__ j(not_equal, slow);
|
__ j(not_equal, slow);
|
||||||
@ -742,9 +739,8 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
|
||||||
MacroAssembler* masm,
|
Label* slow) {
|
||||||
Label* slow) {
|
|
||||||
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
|
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
__ cmp(edx, masm->isolate()->factory()->heap_number_map());
|
__ cmp(edx, masm->isolate()->factory()->heap_number_map());
|
||||||
__ j(not_equal, slow);
|
__ j(not_equal, slow);
|
||||||
@ -803,7 +799,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateGenericStubSub(masm);
|
GenerateGenericStubSub(masm);
|
||||||
@ -817,7 +813,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, undo, slow;
|
Label non_smi, undo, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear);
|
GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -829,7 +825,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -839,8 +835,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
// Handle the slow case by jumping to the corresponding JavaScript builtin.
|
// Handle the slow case by jumping to the corresponding JavaScript builtin.
|
||||||
__ pop(ecx); // pop return address.
|
__ pop(ecx); // pop return address.
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
@ -858,15 +853,15 @@ void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
|
Handle<Code> GetBinaryOpStub(int key,
|
||||||
TRBinaryOpIC::TypeInfo type_info,
|
BinaryOpIC::TypeInfo type_info,
|
||||||
TRBinaryOpIC::TypeInfo result_type_info) {
|
BinaryOpIC::TypeInfo result_type_info) {
|
||||||
TypeRecordingBinaryOpStub stub(key, type_info, result_type_info);
|
BinaryOpStub stub(key, type_info, result_type_info);
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
__ pop(ecx); // Save return address.
|
__ pop(ecx); // Save return address.
|
||||||
__ push(edx);
|
__ push(edx);
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
@ -882,7 +877,7 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
// Patch the caller to an appropriate specialized stub and return the
|
// Patch the caller to an appropriate specialized stub and return the
|
||||||
// operation result to the caller of the stub.
|
// operation result to the caller of the stub.
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
5,
|
5,
|
||||||
1);
|
1);
|
||||||
@ -891,8 +886,7 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
|
|
||||||
// Prepare for a type transition runtime call when the args are already on
|
// Prepare for a type transition runtime call when the args are already on
|
||||||
// the stack, under the return address.
|
// the stack, under the return address.
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
__ pop(ecx); // Save return address.
|
__ pop(ecx); // Save return address.
|
||||||
// Left and right arguments are already on top of the stack.
|
// Left and right arguments are already on top of the stack.
|
||||||
// Push this stub's key. Although the operation and the type info are
|
// Push this stub's key. Although the operation and the type info are
|
||||||
@ -906,37 +900,37 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
|||||||
// Patch the caller to an appropriate specialized stub and return the
|
// Patch the caller to an appropriate specialized stub and return the
|
||||||
// operation result to the caller of the stub.
|
// operation result to the caller of the stub.
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
5,
|
5,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
void BinaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operands_type_) {
|
switch (operands_type_) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
GenerateInt32Stub(masm);
|
GenerateInt32Stub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::ODDBALL:
|
case BinaryOpIC::ODDBALL:
|
||||||
GenerateOddballStub(masm);
|
GenerateOddballStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::BOTH_STRING:
|
case BinaryOpIC::BOTH_STRING:
|
||||||
GenerateBothStringStub(masm);
|
GenerateBothStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::STRING:
|
case BinaryOpIC::STRING:
|
||||||
GenerateStringStub(masm);
|
GenerateStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::GENERIC:
|
case BinaryOpIC::GENERIC:
|
||||||
GenerateGeneric(masm);
|
GenerateGeneric(masm);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -945,7 +939,7 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingBinaryOpStub::GetName() {
|
const char* BinaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -961,15 +955,16 @@ const char* TypeRecordingBinaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingBinaryOpStub_%s_%s_%s",
|
"BinaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
void BinaryOpStub::GenerateSmiCode(
|
||||||
|
MacroAssembler* masm,
|
||||||
Label* slow,
|
Label* slow,
|
||||||
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
||||||
// 1. Move arguments into edx, eax except for DIV and MOD, which need the
|
// 1. Move arguments into edx, eax except for DIV and MOD, which need the
|
||||||
@ -1344,7 +1339,7 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
|
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
@ -1366,8 +1361,8 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
|
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
|
||||||
result_type_ == TRBinaryOpIC::SMI) {
|
result_type_ == BinaryOpIC::SMI) {
|
||||||
GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS);
|
||||||
} else {
|
} else {
|
||||||
GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
||||||
@ -1395,19 +1390,19 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::STRING);
|
ASSERT(operands_type_ == BinaryOpIC::STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
// Try to add arguments as strings, otherwise, transition to the generic
|
// Try to add arguments as strings, otherwise, transition to the generic
|
||||||
// TRBinaryOpIC type.
|
// BinaryOpIC type.
|
||||||
GenerateAddStrings(masm);
|
GenerateAddStrings(masm);
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING);
|
ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
// If both arguments are strings, call the string add stub.
|
// If both arguments are strings, call the string add stub.
|
||||||
// Otherwise, do a transition.
|
// Otherwise, do a transition.
|
||||||
@ -1437,9 +1432,9 @@ void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::INT32);
|
ASSERT(operands_type_ == BinaryOpIC::INT32);
|
||||||
|
|
||||||
// Floating point case.
|
// Floating point case.
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
@ -1461,7 +1456,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
// Check result type if it is currently Int32.
|
// Check result type if it is currently Int32.
|
||||||
if (result_type_ <= TRBinaryOpIC::INT32) {
|
if (result_type_ <= BinaryOpIC::INT32) {
|
||||||
__ cvttsd2si(ecx, Operand(xmm0));
|
__ cvttsd2si(ecx, Operand(xmm0));
|
||||||
__ cvtsi2sd(xmm2, Operand(ecx));
|
__ cvtsi2sd(xmm2, Operand(ecx));
|
||||||
__ ucomisd(xmm0, xmm2);
|
__ ucomisd(xmm0, xmm2);
|
||||||
@ -1639,7 +1634,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||||
if (op_ == Token::ADD) {
|
if (op_ == Token::ADD) {
|
||||||
// Handle string addition here, because it is the only operation
|
// Handle string addition here, because it is the only operation
|
||||||
// that does not do a ToNumber conversion on the operands.
|
// that does not do a ToNumber conversion on the operands.
|
||||||
@ -1672,7 +1667,7 @@ void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
|
|
||||||
// Floating point case.
|
// Floating point case.
|
||||||
@ -1853,7 +1848,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
|
|
||||||
Counters* counters = masm->isolate()->counters();
|
Counters* counters = masm->isolate()->counters();
|
||||||
@ -2050,7 +2045,7 @@ void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
Label left_not_string, call_runtime;
|
Label left_not_string, call_runtime;
|
||||||
|
|
||||||
@ -2084,7 +2079,7 @@ void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
void BinaryOpStub::GenerateHeapResultAllocation(
|
||||||
MacroAssembler* masm,
|
MacroAssembler* masm,
|
||||||
Label* alloc_failure) {
|
Label* alloc_failure) {
|
||||||
Label skip_allocation;
|
Label skip_allocation;
|
||||||
@ -2126,7 +2121,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
||||||
__ pop(ecx);
|
__ pop(ecx);
|
||||||
__ push(edx);
|
__ push(edx);
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
|
@ -72,18 +72,16 @@ class ToBooleanStub: public CodeStub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingUnaryOpStub: public CodeStub {
|
class UnaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingUnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
UnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operand_type_(TRUnaryOpIC::UNINITIALIZED),
|
operand_type_(UnaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingUnaryOpStub(
|
UnaryOpStub(int key, UnaryOpIC::TypeInfo operand_type)
|
||||||
int key,
|
|
||||||
TRUnaryOpIC::TypeInfo operand_type)
|
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
operand_type_(operand_type),
|
operand_type_(operand_type),
|
||||||
@ -95,7 +93,7 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
UnaryOverwriteMode mode_;
|
UnaryOverwriteMode mode_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRUnaryOpIC::TypeInfo operand_type_;
|
UnaryOpIC::TypeInfo operand_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -108,15 +106,15 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
||||||
class OpBits: public BitField<Token::Value, 1, 7> {};
|
class OpBits: public BitField<Token::Value, 1, 7> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRUnaryOpIC::TypeInfo, 8, 3> {};
|
class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingUnaryOp; }
|
Major MajorKey() { return UnaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return ModeBits::encode(mode_)
|
return ModeBits::encode(mode_)
|
||||||
| OpBits::encode(op_)
|
| OpBits::encode(op_)
|
||||||
@ -155,34 +153,34 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
||||||
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_UNARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRUnaryOpIC::ToState(operand_type_);
|
return UnaryOpIC::ToState(operand_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_unary_op_type(operand_type_);
|
code->set_unary_op_type(operand_type_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingBinaryOpStub: public CodeStub {
|
class BinaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
|
BinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operands_type_(TRBinaryOpIC::UNINITIALIZED),
|
operands_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
result_type_(TRBinaryOpIC::UNINITIALIZED),
|
result_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
use_sse3_ = CpuFeatures::IsSupported(SSE3);
|
use_sse3_ = CpuFeatures::IsSupported(SSE3);
|
||||||
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub(
|
BinaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRBinaryOpIC::TypeInfo operands_type,
|
BinaryOpIC::TypeInfo operands_type,
|
||||||
TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
|
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
use_sse3_(SSE3Bits::decode(key)),
|
use_sse3_(SSE3Bits::decode(key)),
|
||||||
@ -201,8 +199,8 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
bool use_sse3_;
|
bool use_sse3_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRBinaryOpIC::TypeInfo operands_type_;
|
BinaryOpIC::TypeInfo operands_type_;
|
||||||
TRBinaryOpIC::TypeInfo result_type_;
|
BinaryOpIC::TypeInfo result_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -210,12 +208,12 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingBinaryOpStub %d (op %s), "
|
PrintF("BinaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -223,10 +221,10 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
||||||
class OpBits: public BitField<Token::Value, 2, 7> {};
|
class OpBits: public BitField<Token::Value, 2, 7> {};
|
||||||
class SSE3Bits: public BitField<bool, 9, 1> {};
|
class SSE3Bits: public BitField<bool, 9, 1> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 10, 3> {};
|
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
|
||||||
class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 13, 3> {};
|
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingBinaryOp; }
|
Major MajorKey() { return BinaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return OpBits::encode(op_)
|
return OpBits::encode(op_)
|
||||||
| ModeBits::encode(mode_)
|
| ModeBits::encode(mode_)
|
||||||
@ -257,15 +255,15 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
void GenerateTypeTransition(MacroAssembler* masm);
|
void GenerateTypeTransition(MacroAssembler* masm);
|
||||||
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRBinaryOpIC::ToState(operands_type_);
|
return BinaryOpIC::ToState(operands_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_binary_op_type(operands_type_);
|
code->set_binary_op_type(operands_type_);
|
||||||
code->set_type_recording_binary_op_result_type(result_type_);
|
code->set_binary_op_result_type(result_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CodeGenerator;
|
friend class CodeGenerator;
|
||||||
|
@ -1662,7 +1662,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
|
|
||||||
__ bind(&stub_call);
|
__ bind(&stub_call);
|
||||||
__ mov(eax, ecx);
|
__ mov(eax, ecx);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
||||||
__ jmp(&done, Label::kNear);
|
__ jmp(&done, Label::kNear);
|
||||||
|
|
||||||
@ -1745,7 +1745,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
|||||||
Token::Value op,
|
Token::Value op,
|
||||||
OverwriteMode mode) {
|
OverwriteMode mode) {
|
||||||
__ pop(edx);
|
__ pop(edx);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
// NULL signals no inlined smi code.
|
// NULL signals no inlined smi code.
|
||||||
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
@ -3751,8 +3751,8 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
|||||||
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
||||||
UnaryOverwriteMode overwrite =
|
UnaryOverwriteMode overwrite =
|
||||||
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
||||||
TypeRecordingUnaryOpStub stub(expr->op(), overwrite);
|
UnaryOpStub stub(expr->op(), overwrite);
|
||||||
// TypeRecordingUnaryOpStub expects the argument to be in the
|
// UnaryOpStub expects the argument to be in the
|
||||||
// accumulator register eax.
|
// accumulator register eax.
|
||||||
VisitForAccumulatorValue(expr->expression());
|
VisitForAccumulatorValue(expr->expression());
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
@ -3884,7 +3884,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
// Call stub for +1/-1.
|
// Call stub for +1/-1.
|
||||||
__ mov(edx, eax);
|
__ mov(edx, eax);
|
||||||
__ mov(eax, Immediate(Smi::FromInt(1)));
|
__ mov(eax, Immediate(Smi::FromInt(1)));
|
||||||
TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
|
BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
|
|
||||||
|
@ -428,7 +428,7 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
|
|||||||
|
|
||||||
// Signal that we don't inline smi code before these stubs in the
|
// Signal that we don't inline smi code before these stubs in the
|
||||||
// optimizing code generator.
|
// optimizing code generator.
|
||||||
if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC ||
|
if (code->kind() == Code::BINARY_OP_IC ||
|
||||||
code->kind() == Code::COMPARE_IC) {
|
code->kind() == Code::COMPARE_IC) {
|
||||||
__ nop();
|
__ nop();
|
||||||
}
|
}
|
||||||
@ -1300,7 +1300,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
|||||||
ASSERT(ToRegister(instr->InputAt(1)).is(eax));
|
ASSERT(ToRegister(instr->InputAt(1)).is(eax));
|
||||||
ASSERT(ToRegister(instr->result()).is(eax));
|
ASSERT(ToRegister(instr->result()).is(eax));
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
BinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
125
src/ic.cc
125
src/ic.cc
@ -306,8 +306,8 @@ void IC::Clear(Address address) {
|
|||||||
return KeyedStoreIC::Clear(address, target);
|
return KeyedStoreIC::Clear(address, target);
|
||||||
case Code::CALL_IC: return CallIC::Clear(address, target);
|
case Code::CALL_IC: return CallIC::Clear(address, target);
|
||||||
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
|
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
|
||||||
case Code::TYPE_RECORDING_UNARY_OP_IC:
|
case Code::UNARY_OP_IC:
|
||||||
case Code::TYPE_RECORDING_BINARY_OP_IC:
|
case Code::BINARY_OP_IC:
|
||||||
case Code::COMPARE_IC:
|
case Code::COMPARE_IC:
|
||||||
// Clearing these is tricky and does not
|
// Clearing these is tricky and does not
|
||||||
// make any performance difference.
|
// make any performance difference.
|
||||||
@ -2157,12 +2157,12 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRUnaryOpIC::patch(Code* code) {
|
void UnaryOpIC::patch(Code* code) {
|
||||||
set_target(code);
|
set_target(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TRUnaryOpIC::GetName(TypeInfo type_info) {
|
const char* UnaryOpIC::GetName(TypeInfo type_info) {
|
||||||
switch (type_info) {
|
switch (type_info) {
|
||||||
case UNINITIALIZED: return "Uninitialized";
|
case UNINITIALIZED: return "Uninitialized";
|
||||||
case SMI: return "Smi";
|
case SMI: return "Smi";
|
||||||
@ -2173,7 +2173,7 @@ const char* TRUnaryOpIC::GetName(TypeInfo type_info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRUnaryOpIC::State TRUnaryOpIC::ToState(TypeInfo type_info) {
|
UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) {
|
||||||
switch (type_info) {
|
switch (type_info) {
|
||||||
case UNINITIALIZED:
|
case UNINITIALIZED:
|
||||||
return ::v8::internal::UNINITIALIZED;
|
return ::v8::internal::UNINITIALIZED;
|
||||||
@ -2187,7 +2187,7 @@ TRUnaryOpIC::State TRUnaryOpIC::ToState(TypeInfo type_info) {
|
|||||||
return ::v8::internal::UNINITIALIZED;
|
return ::v8::internal::UNINITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRUnaryOpIC::TypeInfo TRUnaryOpIC::GetTypeInfo(Handle<Object> operand) {
|
UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
|
||||||
::v8::internal::TypeInfo operand_type =
|
::v8::internal::TypeInfo operand_type =
|
||||||
::v8::internal::TypeInfo::TypeFromValue(operand);
|
::v8::internal::TypeInfo::TypeFromValue(operand);
|
||||||
if (operand_type.IsSmi()) {
|
if (operand_type.IsSmi()) {
|
||||||
@ -2200,34 +2200,34 @@ TRUnaryOpIC::TypeInfo TRUnaryOpIC::GetTypeInfo(Handle<Object> operand) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRUnaryOpIC::TypeInfo TRUnaryOpIC::ComputeNewType(
|
UnaryOpIC::TypeInfo UnaryOpIC::ComputeNewType(
|
||||||
TRUnaryOpIC::TypeInfo type,
|
UnaryOpIC::TypeInfo current_type,
|
||||||
TRUnaryOpIC::TypeInfo previous) {
|
UnaryOpIC::TypeInfo previous_type) {
|
||||||
switch (previous) {
|
switch (previous_type) {
|
||||||
case TRUnaryOpIC::UNINITIALIZED:
|
case UnaryOpIC::UNINITIALIZED:
|
||||||
return type;
|
return current_type;
|
||||||
case TRUnaryOpIC::SMI:
|
case UnaryOpIC::SMI:
|
||||||
return (type == TRUnaryOpIC::GENERIC)
|
return (current_type == UnaryOpIC::GENERIC)
|
||||||
? TRUnaryOpIC::GENERIC
|
? UnaryOpIC::GENERIC
|
||||||
: TRUnaryOpIC::HEAP_NUMBER;
|
: UnaryOpIC::HEAP_NUMBER;
|
||||||
case TRUnaryOpIC::HEAP_NUMBER:
|
case UnaryOpIC::HEAP_NUMBER:
|
||||||
return TRUnaryOpIC::GENERIC;
|
return UnaryOpIC::GENERIC;
|
||||||
case TRUnaryOpIC::GENERIC:
|
case UnaryOpIC::GENERIC:
|
||||||
// We should never do patching if we are in GENERIC state.
|
// We should never do patching if we are in GENERIC state.
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return TRUnaryOpIC::GENERIC;
|
return UnaryOpIC::GENERIC;
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return TRUnaryOpIC::GENERIC;
|
return UnaryOpIC::GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRBinaryOpIC::patch(Code* code) {
|
void BinaryOpIC::patch(Code* code) {
|
||||||
set_target(code);
|
set_target(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
|
const char* BinaryOpIC::GetName(TypeInfo type_info) {
|
||||||
switch (type_info) {
|
switch (type_info) {
|
||||||
case UNINITIALIZED: return "Uninitialized";
|
case UNINITIALIZED: return "Uninitialized";
|
||||||
case SMI: return "SMI";
|
case SMI: return "SMI";
|
||||||
@ -2242,7 +2242,7 @@ const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRBinaryOpIC::State TRBinaryOpIC::ToState(TypeInfo type_info) {
|
BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
|
||||||
switch (type_info) {
|
switch (type_info) {
|
||||||
case UNINITIALIZED:
|
case UNINITIALIZED:
|
||||||
return ::v8::internal::UNINITIALIZED;
|
return ::v8::internal::UNINITIALIZED;
|
||||||
@ -2261,8 +2261,8 @@ TRBinaryOpIC::State TRBinaryOpIC::ToState(TypeInfo type_info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRBinaryOpIC::TypeInfo TRBinaryOpIC::JoinTypes(TRBinaryOpIC::TypeInfo x,
|
BinaryOpIC::TypeInfo BinaryOpIC::JoinTypes(BinaryOpIC::TypeInfo x,
|
||||||
TRBinaryOpIC::TypeInfo y) {
|
BinaryOpIC::TypeInfo y) {
|
||||||
if (x == UNINITIALIZED) return y;
|
if (x == UNINITIALIZED) return y;
|
||||||
if (y == UNINITIALIZED) return x;
|
if (y == UNINITIALIZED) return x;
|
||||||
if (x == y) return x;
|
if (x == y) return x;
|
||||||
@ -2276,8 +2276,8 @@ TRBinaryOpIC::TypeInfo TRBinaryOpIC::JoinTypes(TRBinaryOpIC::TypeInfo x,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRBinaryOpIC::TypeInfo TRBinaryOpIC::GetTypeInfo(Handle<Object> left,
|
BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Handle<Object> left,
|
||||||
Handle<Object> right) {
|
Handle<Object> right) {
|
||||||
::v8::internal::TypeInfo left_type =
|
::v8::internal::TypeInfo left_type =
|
||||||
::v8::internal::TypeInfo::TypeFromValue(left);
|
::v8::internal::TypeInfo::TypeFromValue(left);
|
||||||
::v8::internal::TypeInfo right_type =
|
::v8::internal::TypeInfo right_type =
|
||||||
@ -2315,32 +2315,31 @@ TRBinaryOpIC::TypeInfo TRBinaryOpIC::GetTypeInfo(Handle<Object> left,
|
|||||||
|
|
||||||
// defined in code-stubs-<arch>.cc
|
// defined in code-stubs-<arch>.cc
|
||||||
// Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
|
// Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
|
||||||
Handle<Code> GetTypeRecordingUnaryOpStub(int key,
|
Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info);
|
||||||
TRUnaryOpIC::TypeInfo type_info);
|
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(MaybeObject*, TypeRecordingUnaryOp_Patch) {
|
RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
|
||||||
ASSERT(args.length() == 4);
|
ASSERT(args.length() == 4);
|
||||||
|
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
Handle<Object> operand = args.at<Object>(0);
|
Handle<Object> operand = args.at<Object>(0);
|
||||||
int key = Smi::cast(args[1])->value();
|
int key = Smi::cast(args[1])->value();
|
||||||
Token::Value op = static_cast<Token::Value>(Smi::cast(args[2])->value());
|
Token::Value op = static_cast<Token::Value>(Smi::cast(args[2])->value());
|
||||||
TRUnaryOpIC::TypeInfo previous_type =
|
UnaryOpIC::TypeInfo previous_type =
|
||||||
static_cast<TRUnaryOpIC::TypeInfo>(Smi::cast(args[3])->value());
|
static_cast<UnaryOpIC::TypeInfo>(Smi::cast(args[3])->value());
|
||||||
|
|
||||||
TRUnaryOpIC::TypeInfo type = TRUnaryOpIC::GetTypeInfo(operand);
|
UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand);
|
||||||
type = TRUnaryOpIC::ComputeNewType(type, previous_type);
|
type = UnaryOpIC::ComputeNewType(type, previous_type);
|
||||||
|
|
||||||
Handle<Code> code = GetTypeRecordingUnaryOpStub(key, type);
|
Handle<Code> code = GetUnaryOpStub(key, type);
|
||||||
if (!code.is_null()) {
|
if (!code.is_null()) {
|
||||||
if (FLAG_trace_ic) {
|
if (FLAG_trace_ic) {
|
||||||
PrintF("[TypeRecordingUnaryOpIC (%s->%s)#%s]\n",
|
PrintF("[UnaryOpIC (%s->%s)#%s]\n",
|
||||||
TRUnaryOpIC::GetName(previous_type),
|
UnaryOpIC::GetName(previous_type),
|
||||||
TRUnaryOpIC::GetName(type),
|
UnaryOpIC::GetName(type),
|
||||||
Token::Name(op));
|
Token::Name(op));
|
||||||
}
|
}
|
||||||
TRUnaryOpIC ic(isolate);
|
UnaryOpIC ic(isolate);
|
||||||
ic.patch(*code);
|
ic.patch(*code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2371,12 +2370,12 @@ RUNTIME_FUNCTION(MaybeObject*, TypeRecordingUnaryOp_Patch) {
|
|||||||
|
|
||||||
// defined in code-stubs-<arch>.cc
|
// defined in code-stubs-<arch>.cc
|
||||||
// Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
|
// Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
|
||||||
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
|
Handle<Code> GetBinaryOpStub(int key,
|
||||||
TRBinaryOpIC::TypeInfo type_info,
|
BinaryOpIC::TypeInfo type_info,
|
||||||
TRBinaryOpIC::TypeInfo result_type);
|
BinaryOpIC::TypeInfo result_type);
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(MaybeObject*, TypeRecordingBinaryOp_Patch) {
|
RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
|
||||||
ASSERT(args.length() == 5);
|
ASSERT(args.length() == 5);
|
||||||
|
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
@ -2384,17 +2383,17 @@ RUNTIME_FUNCTION(MaybeObject*, TypeRecordingBinaryOp_Patch) {
|
|||||||
Handle<Object> right = args.at<Object>(1);
|
Handle<Object> right = args.at<Object>(1);
|
||||||
int key = Smi::cast(args[2])->value();
|
int key = Smi::cast(args[2])->value();
|
||||||
Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
|
Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
|
||||||
TRBinaryOpIC::TypeInfo previous_type =
|
BinaryOpIC::TypeInfo previous_type =
|
||||||
static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
|
static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
|
||||||
|
|
||||||
TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right);
|
BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right);
|
||||||
type = TRBinaryOpIC::JoinTypes(type, previous_type);
|
type = BinaryOpIC::JoinTypes(type, previous_type);
|
||||||
TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED;
|
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
|
||||||
if ((type == TRBinaryOpIC::STRING || type == TRBinaryOpIC::BOTH_STRING) &&
|
if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) &&
|
||||||
op != Token::ADD) {
|
op != Token::ADD) {
|
||||||
type = TRBinaryOpIC::GENERIC;
|
type = BinaryOpIC::GENERIC;
|
||||||
}
|
}
|
||||||
if (type == TRBinaryOpIC::SMI && previous_type == TRBinaryOpIC::SMI) {
|
if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) {
|
||||||
if (op == Token::DIV ||
|
if (op == Token::DIV ||
|
||||||
op == Token::MUL ||
|
op == Token::MUL ||
|
||||||
op == Token::SHR ||
|
op == Token::SHR ||
|
||||||
@ -2403,31 +2402,31 @@ RUNTIME_FUNCTION(MaybeObject*, TypeRecordingBinaryOp_Patch) {
|
|||||||
// That is the only way to get here from the Smi stub.
|
// That is the only way to get here from the Smi stub.
|
||||||
// With 32-bit Smis, all overflows give heap numbers, but with
|
// With 32-bit Smis, all overflows give heap numbers, but with
|
||||||
// 31-bit Smis, most operations overflow to int32 results.
|
// 31-bit Smis, most operations overflow to int32 results.
|
||||||
result_type = TRBinaryOpIC::HEAP_NUMBER;
|
result_type = BinaryOpIC::HEAP_NUMBER;
|
||||||
} else {
|
} else {
|
||||||
// Other operations on SMIs that overflow yield int32s.
|
// Other operations on SMIs that overflow yield int32s.
|
||||||
result_type = TRBinaryOpIC::INT32;
|
result_type = BinaryOpIC::INT32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == TRBinaryOpIC::INT32 && previous_type == TRBinaryOpIC::INT32) {
|
if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) {
|
||||||
// We must be here because an operation on two INT32 types overflowed.
|
// We must be here because an operation on two INT32 types overflowed.
|
||||||
result_type = TRBinaryOpIC::HEAP_NUMBER;
|
result_type = BinaryOpIC::HEAP_NUMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type);
|
Handle<Code> code = GetBinaryOpStub(key, type, result_type);
|
||||||
if (!code.is_null()) {
|
if (!code.is_null()) {
|
||||||
if (FLAG_trace_ic) {
|
if (FLAG_trace_ic) {
|
||||||
PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n",
|
PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n",
|
||||||
TRBinaryOpIC::GetName(previous_type),
|
BinaryOpIC::GetName(previous_type),
|
||||||
TRBinaryOpIC::GetName(type),
|
BinaryOpIC::GetName(type),
|
||||||
TRBinaryOpIC::GetName(result_type),
|
BinaryOpIC::GetName(result_type),
|
||||||
Token::Name(op));
|
Token::Name(op));
|
||||||
}
|
}
|
||||||
TRBinaryOpIC ic(isolate);
|
BinaryOpIC ic(isolate);
|
||||||
ic.patch(*code);
|
ic.patch(*code);
|
||||||
|
|
||||||
// Activate inlined smi code.
|
// Activate inlined smi code.
|
||||||
if (previous_type == TRBinaryOpIC::UNINITIALIZED) {
|
if (previous_type == BinaryOpIC::UNINITIALIZED) {
|
||||||
PatchInlinedSmiCode(ic.address());
|
PatchInlinedSmiCode(ic.address());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
src/ic.h
14
src/ic.h
@ -56,8 +56,8 @@ namespace internal {
|
|||||||
ICU(LoadPropertyWithInterceptorForCall) \
|
ICU(LoadPropertyWithInterceptorForCall) \
|
||||||
ICU(KeyedLoadPropertyWithInterceptor) \
|
ICU(KeyedLoadPropertyWithInterceptor) \
|
||||||
ICU(StoreInterceptorProperty) \
|
ICU(StoreInterceptorProperty) \
|
||||||
ICU(TypeRecordingUnaryOp_Patch) \
|
ICU(UnaryOp_Patch) \
|
||||||
ICU(TypeRecordingBinaryOp_Patch) \
|
ICU(BinaryOp_Patch) \
|
||||||
ICU(CompareIC_Miss)
|
ICU(CompareIC_Miss)
|
||||||
//
|
//
|
||||||
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
|
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
|
||||||
@ -621,7 +621,7 @@ class KeyedStoreIC: public KeyedIC {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TRUnaryOpIC: public IC {
|
class UnaryOpIC: public IC {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// sorted: increasingly more unspecific (ignoring UNINITIALIZED)
|
// sorted: increasingly more unspecific (ignoring UNINITIALIZED)
|
||||||
@ -633,7 +633,7 @@ class TRUnaryOpIC: public IC {
|
|||||||
GENERIC
|
GENERIC
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit TRUnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
|
explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
|
||||||
|
|
||||||
void patch(Code* code);
|
void patch(Code* code);
|
||||||
|
|
||||||
@ -648,7 +648,7 @@ class TRUnaryOpIC: public IC {
|
|||||||
|
|
||||||
|
|
||||||
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
|
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
|
||||||
class TRBinaryOpIC: public IC {
|
class BinaryOpIC: public IC {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum TypeInfo {
|
enum TypeInfo {
|
||||||
@ -662,7 +662,7 @@ class TRBinaryOpIC: public IC {
|
|||||||
GENERIC
|
GENERIC
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit TRBinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
|
explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
|
||||||
|
|
||||||
void patch(Code* code);
|
void patch(Code* code);
|
||||||
|
|
||||||
@ -716,7 +716,7 @@ class CompareIC: public IC {
|
|||||||
Token::Value op_;
|
Token::Value op_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper for TRBinaryOpIC and CompareIC.
|
// Helper for BinaryOpIC and CompareIC.
|
||||||
void PatchInlinedSmiCode(Address address);
|
void PatchInlinedSmiCode(Address address);
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -1604,8 +1604,8 @@ void Logger::LogCodeObject(Object* object) {
|
|||||||
case Code::FUNCTION:
|
case Code::FUNCTION:
|
||||||
case Code::OPTIMIZED_FUNCTION:
|
case Code::OPTIMIZED_FUNCTION:
|
||||||
return; // We log this later using LogCompiledFunctions.
|
return; // We log this later using LogCompiledFunctions.
|
||||||
case Code::TYPE_RECORDING_UNARY_OP_IC: // fall through
|
case Code::UNARY_OP_IC: // fall through
|
||||||
case Code::TYPE_RECORDING_BINARY_OP_IC: // fall through
|
case Code::BINARY_OP_IC: // fall through
|
||||||
case Code::COMPARE_IC: // fall through
|
case Code::COMPARE_IC: // fall through
|
||||||
case Code::STUB:
|
case Code::STUB:
|
||||||
description =
|
description =
|
||||||
|
@ -1807,14 +1807,13 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingUnaryOpStub(int key,
|
Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
|
||||||
TRUnaryOpIC::TypeInfo type_info) {
|
UnaryOpStub stub(key, type_info);
|
||||||
TypeRecordingUnaryOpStub stub(key, type_info);
|
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingUnaryOpStub::GetName() {
|
const char* UnaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -1828,34 +1827,34 @@ const char* TypeRecordingUnaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingUnaryOpStub_%s_%s_%s",
|
"UnaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) {
|
void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operand_type_) {
|
switch (operand_type_) {
|
||||||
case TRUnaryOpIC::UNINITIALIZED:
|
case UnaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::SMI:
|
case UnaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::HEAP_NUMBER:
|
case UnaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::GENERIC:
|
case UnaryOpIC::GENERIC:
|
||||||
GenerateGenericStub(masm);
|
GenerateGenericStub(masm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
// Argument is in a0 and v0 at this point, so we can overwrite a0.
|
// Argument is in a0 and v0 at this point, so we can overwrite a0.
|
||||||
// Push this stub's key. Although the operation and the type info are
|
// Push this stub's key. Although the operation and the type info are
|
||||||
// encoded into the key, the encoding is opaque, so push them too.
|
// encoded into the key, the encoding is opaque, so push them too.
|
||||||
@ -1866,7 +1865,7 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
__ Push(v0, a2, a1, a0);
|
__ Push(v0, a2, a1, a0);
|
||||||
|
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kUnaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
4,
|
4,
|
||||||
1);
|
1);
|
||||||
@ -1874,7 +1873,7 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateSmiStubSub(masm);
|
GenerateSmiStubSub(masm);
|
||||||
@ -1888,7 +1887,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1897,7 +1896,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi;
|
Label non_smi;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1905,9 +1904,9 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
||||||
Label* non_smi,
|
Label* non_smi,
|
||||||
Label* slow) {
|
Label* slow) {
|
||||||
__ JumpIfNotSmi(a0, non_smi);
|
__ JumpIfNotSmi(a0, non_smi);
|
||||||
|
|
||||||
// The result of negating zero or the smallest negative smi is not a smi.
|
// The result of negating zero or the smallest negative smi is not a smi.
|
||||||
@ -1920,8 +1919,8 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
||||||
Label* non_smi) {
|
Label* non_smi) {
|
||||||
__ JumpIfNotSmi(a0, non_smi);
|
__ JumpIfNotSmi(a0, non_smi);
|
||||||
|
|
||||||
// Flip bits and revert inverted smi-tag.
|
// Flip bits and revert inverted smi-tag.
|
||||||
@ -1932,7 +1931,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateHeapNumberStubSub(masm);
|
GenerateHeapNumberStubSub(masm);
|
||||||
@ -1946,7 +1945,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow, call_builtin;
|
Label non_smi, slow, call_builtin;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
|
GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1958,8 +1957,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -1968,8 +1966,8 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
|||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
||||||
Label* slow) {
|
Label* slow) {
|
||||||
EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
|
EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
|
||||||
// a0 is a heap number. Get a new heap number in a1.
|
// a0 is a heap number. Get a new heap number in a1.
|
||||||
if (mode_ == UNARY_OVERWRITE) {
|
if (mode_ == UNARY_OVERWRITE) {
|
||||||
@ -2001,8 +1999,9 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
void UnaryOpStub::GenerateHeapNumberCodeBitNot(
|
||||||
MacroAssembler* masm, Label* slow) {
|
MacroAssembler* masm,
|
||||||
|
Label* slow) {
|
||||||
EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
|
EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
|
||||||
// Convert the heap number in a0 to an untagged integer in a1.
|
// Convert the heap number in a0 to an untagged integer in a1.
|
||||||
__ ConvertToInt32(a0, a1, a2, a3, f0, slow);
|
__ ConvertToInt32(a0, a1, a2, a3, f0, slow);
|
||||||
@ -2051,7 +2050,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateGenericStubSub(masm);
|
GenerateGenericStubSub(masm);
|
||||||
@ -2065,7 +2064,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
GenerateSmiCodeSub(masm, &non_smi, &slow);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -2075,7 +2074,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi);
|
GenerateSmiCodeBitNot(masm, &non_smi);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -2085,7 +2084,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
void UnaryOpStub::GenerateGenericCodeFallback(
|
||||||
MacroAssembler* masm) {
|
MacroAssembler* masm) {
|
||||||
// Handle the slow case by jumping to the JavaScript builtin.
|
// Handle the slow case by jumping to the JavaScript builtin.
|
||||||
__ push(a0);
|
__ push(a0);
|
||||||
@ -2102,15 +2101,15 @@ void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
|
Handle<Code> GetBinaryOpStub(int key,
|
||||||
TRBinaryOpIC::TypeInfo type_info,
|
BinaryOpIC::TypeInfo type_info,
|
||||||
TRBinaryOpIC::TypeInfo result_type_info) {
|
BinaryOpIC::TypeInfo result_type_info) {
|
||||||
TypeRecordingBinaryOpStub stub(key, type_info, result_type_info);
|
BinaryOpStub stub(key, type_info, result_type_info);
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
Label get_result;
|
Label get_result;
|
||||||
|
|
||||||
__ Push(a1, a0);
|
__ Push(a1, a0);
|
||||||
@ -2121,43 +2120,43 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
__ Push(a2, a1, a0);
|
__ Push(a2, a1, a0);
|
||||||
|
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
5,
|
5,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
||||||
MacroAssembler* masm) {
|
MacroAssembler* masm) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
void BinaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operands_type_) {
|
switch (operands_type_) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
GenerateInt32Stub(masm);
|
GenerateInt32Stub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::ODDBALL:
|
case BinaryOpIC::ODDBALL:
|
||||||
GenerateOddballStub(masm);
|
GenerateOddballStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::BOTH_STRING:
|
case BinaryOpIC::BOTH_STRING:
|
||||||
GenerateBothStringStub(masm);
|
GenerateBothStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::STRING:
|
case BinaryOpIC::STRING:
|
||||||
GenerateStringStub(masm);
|
GenerateStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::GENERIC:
|
case BinaryOpIC::GENERIC:
|
||||||
GenerateGeneric(masm);
|
GenerateGeneric(masm);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2166,7 +2165,7 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingBinaryOpStub::GetName() {
|
const char* BinaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -2182,17 +2181,16 @@ const char* TypeRecordingBinaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingBinaryOpStub_%s_%s_%s",
|
"BinaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
|
void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
Register left = a1;
|
Register left = a1;
|
||||||
Register right = a0;
|
Register right = a0;
|
||||||
|
|
||||||
@ -2346,10 +2344,10 @@ void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
||||||
bool smi_operands,
|
bool smi_operands,
|
||||||
Label* not_numbers,
|
Label* not_numbers,
|
||||||
Label* gc_required) {
|
Label* gc_required) {
|
||||||
Register left = a1;
|
Register left = a1;
|
||||||
Register right = a0;
|
Register right = a0;
|
||||||
Register scratch1 = t3;
|
Register scratch1 = t3;
|
||||||
@ -2562,7 +2560,8 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
|||||||
// generated. If the result is not a smi and heap number allocation is not
|
// generated. If the result is not a smi and heap number allocation is not
|
||||||
// requested the code falls through. If number allocation is requested but a
|
// requested the code falls through. If number allocation is requested but a
|
||||||
// heap number cannot be allocated the code jumps to the lable gc_required.
|
// heap number cannot be allocated the code jumps to the lable gc_required.
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
void BinaryOpStub::GenerateSmiCode(
|
||||||
|
MacroAssembler* masm,
|
||||||
Label* use_runtime,
|
Label* use_runtime,
|
||||||
Label* gc_required,
|
Label* gc_required,
|
||||||
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
||||||
@ -2590,11 +2589,11 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
Label not_smis, call_runtime;
|
Label not_smis, call_runtime;
|
||||||
|
|
||||||
if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
|
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
|
||||||
result_type_ == TRBinaryOpIC::SMI) {
|
result_type_ == BinaryOpIC::SMI) {
|
||||||
// Only allow smi results.
|
// Only allow smi results.
|
||||||
GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
|
||||||
} else {
|
} else {
|
||||||
@ -2615,18 +2614,18 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::STRING);
|
ASSERT(operands_type_ == BinaryOpIC::STRING);
|
||||||
// Try to add arguments as strings, otherwise, transition to the generic
|
// Try to add arguments as strings, otherwise, transition to the generic
|
||||||
// TRBinaryOpIC type.
|
// BinaryOpIC type.
|
||||||
GenerateAddStrings(masm);
|
GenerateAddStrings(masm);
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING);
|
ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
// If both arguments are strings, call the string add stub.
|
// If both arguments are strings, call the string add stub.
|
||||||
// Otherwise, do a transition.
|
// Otherwise, do a transition.
|
||||||
@ -2654,8 +2653,8 @@ void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::INT32);
|
ASSERT(operands_type_ == BinaryOpIC::INT32);
|
||||||
|
|
||||||
Register left = a1;
|
Register left = a1;
|
||||||
Register right = a0;
|
Register right = a0;
|
||||||
@ -2764,7 +2763,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
__ srl(scratch2, scratch2, kFCSRFlagShift);
|
__ srl(scratch2, scratch2, kFCSRFlagShift);
|
||||||
__ And(scratch2, scratch2, kFCSRFlagMask);
|
__ And(scratch2, scratch2, kFCSRFlagMask);
|
||||||
|
|
||||||
if (result_type_ <= TRBinaryOpIC::INT32) {
|
if (result_type_ <= BinaryOpIC::INT32) {
|
||||||
// If scratch2 != 0, result does not fit in a 32-bit integer.
|
// If scratch2 != 0, result does not fit in a 32-bit integer.
|
||||||
__ Branch(&transition, ne, scratch2, Operand(zero_reg));
|
__ Branch(&transition, ne, scratch2, Operand(zero_reg));
|
||||||
}
|
}
|
||||||
@ -2789,8 +2788,8 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
// DIV just falls through to allocating a heap number.
|
// DIV just falls through to allocating a heap number.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result_type_ >= (op_ == Token::DIV) ? TRBinaryOpIC::HEAP_NUMBER
|
if (result_type_ >= (op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
|
||||||
: TRBinaryOpIC::INT32) {
|
: BinaryOpIC::INT32) {
|
||||||
__ bind(&return_heap_number);
|
__ bind(&return_heap_number);
|
||||||
// We are using FPU registers so s0 is available.
|
// We are using FPU registers so s0 is available.
|
||||||
heap_number_result = s0;
|
heap_number_result = s0;
|
||||||
@ -2898,14 +2897,14 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
// The non FPU code does not support this special case, so jump to
|
// The non FPU code does not support this special case, so jump to
|
||||||
// runtime if we don't support it.
|
// runtime if we don't support it.
|
||||||
if (CpuFeatures::IsSupported(FPU)) {
|
if (CpuFeatures::IsSupported(FPU)) {
|
||||||
__ Branch((result_type_ <= TRBinaryOpIC::INT32)
|
__ Branch((result_type_ <= BinaryOpIC::INT32)
|
||||||
? &transition
|
? &transition
|
||||||
: &return_heap_number,
|
: &return_heap_number,
|
||||||
lt,
|
lt,
|
||||||
a2,
|
a2,
|
||||||
Operand(zero_reg));
|
Operand(zero_reg));
|
||||||
} else {
|
} else {
|
||||||
__ Branch((result_type_ <= TRBinaryOpIC::INT32)
|
__ Branch((result_type_ <= BinaryOpIC::INT32)
|
||||||
? &transition
|
? &transition
|
||||||
: &call_runtime,
|
: &call_runtime,
|
||||||
lt,
|
lt,
|
||||||
@ -2980,7 +2979,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
|
|
||||||
if (op_ == Token::ADD) {
|
if (op_ == Token::ADD) {
|
||||||
@ -3013,7 +3012,7 @@ void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
|
GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
|
||||||
|
|
||||||
@ -3022,7 +3021,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
||||||
Label call_runtime, call_string_add_or_runtime;
|
Label call_runtime, call_string_add_or_runtime;
|
||||||
|
|
||||||
GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
||||||
@ -3039,7 +3038,7 @@ void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
Label left_not_string, call_runtime;
|
Label left_not_string, call_runtime;
|
||||||
|
|
||||||
@ -3070,7 +3069,7 @@ void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
|
||||||
GenerateRegisterArgsPush(masm);
|
GenerateRegisterArgsPush(masm);
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::ADD:
|
case Token::ADD:
|
||||||
@ -3112,7 +3111,7 @@ void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
void BinaryOpStub::GenerateHeapResultAllocation(
|
||||||
MacroAssembler* masm,
|
MacroAssembler* masm,
|
||||||
Register result,
|
Register result,
|
||||||
Register heap_number_map,
|
Register heap_number_map,
|
||||||
@ -3146,7 +3145,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
||||||
__ Push(a1, a0);
|
__ Push(a1, a0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,18 +72,18 @@ class ToBooleanStub: public CodeStub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingUnaryOpStub: public CodeStub {
|
class UnaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingUnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
UnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operand_type_(TRUnaryOpIC::UNINITIALIZED),
|
operand_type_(UnaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingUnaryOpStub(
|
UnaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRUnaryOpIC::TypeInfo operand_type)
|
UnaryOpIC::TypeInfo operand_type)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
operand_type_(operand_type),
|
operand_type_(operand_type),
|
||||||
@ -95,7 +95,7 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
UnaryOverwriteMode mode_;
|
UnaryOverwriteMode mode_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRUnaryOpIC::TypeInfo operand_type_;
|
UnaryOpIC::TypeInfo operand_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -103,20 +103,20 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingUnaryOpStub %d (op %s), "
|
PrintF("UnaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
||||||
class OpBits: public BitField<Token::Value, 1, 7> {};
|
class OpBits: public BitField<Token::Value, 1, 7> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRUnaryOpIC::TypeInfo, 8, 3> {};
|
class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingUnaryOp; }
|
Major MajorKey() { return UnaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return ModeBits::encode(mode_)
|
return ModeBits::encode(mode_)
|
||||||
| OpBits::encode(op_)
|
| OpBits::encode(op_)
|
||||||
@ -146,34 +146,34 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
||||||
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_UNARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRUnaryOpIC::ToState(operand_type_);
|
return UnaryOpIC::ToState(operand_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_unary_op_type(operand_type_);
|
code->set_unary_op_type(operand_type_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingBinaryOpStub: public CodeStub {
|
class BinaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
|
BinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operands_type_(TRBinaryOpIC::UNINITIALIZED),
|
operands_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
result_type_(TRBinaryOpIC::UNINITIALIZED),
|
result_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
use_fpu_ = CpuFeatures::IsSupported(FPU);
|
use_fpu_ = CpuFeatures::IsSupported(FPU);
|
||||||
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub(
|
BinaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRBinaryOpIC::TypeInfo operands_type,
|
BinaryOpIC::TypeInfo operands_type,
|
||||||
TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
|
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
use_fpu_(FPUBits::decode(key)),
|
use_fpu_(FPUBits::decode(key)),
|
||||||
@ -192,8 +192,8 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
bool use_fpu_;
|
bool use_fpu_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRBinaryOpIC::TypeInfo operands_type_;
|
BinaryOpIC::TypeInfo operands_type_;
|
||||||
TRBinaryOpIC::TypeInfo result_type_;
|
BinaryOpIC::TypeInfo result_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -201,12 +201,12 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingBinaryOpStub %d (op %s), "
|
PrintF("BinaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -214,10 +214,10 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
||||||
class OpBits: public BitField<Token::Value, 2, 7> {};
|
class OpBits: public BitField<Token::Value, 2, 7> {};
|
||||||
class FPUBits: public BitField<bool, 9, 1> {};
|
class FPUBits: public BitField<bool, 9, 1> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 10, 3> {};
|
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
|
||||||
class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 13, 3> {};
|
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingBinaryOp; }
|
Major MajorKey() { return BinaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return OpBits::encode(op_)
|
return OpBits::encode(op_)
|
||||||
| ModeBits::encode(mode_)
|
| ModeBits::encode(mode_)
|
||||||
@ -260,15 +260,15 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
void GenerateTypeTransition(MacroAssembler* masm);
|
void GenerateTypeTransition(MacroAssembler* masm);
|
||||||
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRBinaryOpIC::ToState(operands_type_);
|
return BinaryOpIC::ToState(operands_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_binary_op_type(operands_type_);
|
code->set_binary_op_type(operands_type_);
|
||||||
code->set_type_recording_binary_op_result_type(result_type_);
|
code->set_binary_op_result_type(result_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CodeGenerator;
|
friend class CodeGenerator;
|
||||||
|
@ -1723,14 +1723,14 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
patch_site.EmitJumpIfSmi(scratch1, &smi_case);
|
patch_site.EmitJumpIfSmi(scratch1, &smi_case);
|
||||||
|
|
||||||
__ bind(&stub_call);
|
__ bind(&stub_call);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
||||||
__ jmp(&done);
|
__ jmp(&done);
|
||||||
|
|
||||||
__ bind(&smi_case);
|
__ bind(&smi_case);
|
||||||
// Smi case. This code works the same way as the smi-smi case in the type
|
// Smi case. This code works the same way as the smi-smi case in the type
|
||||||
// recording binary operation stub, see
|
// recording binary operation stub, see
|
||||||
// TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments.
|
// BinaryOpStub::GenerateSmiSmiOperation for comments.
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Token::SAR:
|
case Token::SAR:
|
||||||
__ Branch(&stub_call);
|
__ Branch(&stub_call);
|
||||||
@ -1804,7 +1804,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
|||||||
OverwriteMode mode) {
|
OverwriteMode mode) {
|
||||||
__ mov(a0, result_register());
|
__ mov(a0, result_register());
|
||||||
__ pop(a1);
|
__ pop(a1);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
||||||
context()->Plug(v0);
|
context()->Plug(v0);
|
||||||
}
|
}
|
||||||
@ -3807,8 +3807,8 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
|||||||
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
||||||
UnaryOverwriteMode overwrite =
|
UnaryOverwriteMode overwrite =
|
||||||
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
||||||
TypeRecordingUnaryOpStub stub(expr->op(), overwrite);
|
UnaryOpStub stub(expr->op(), overwrite);
|
||||||
// TypeRecordingGenericUnaryOpStub expects the argument to be in a0.
|
// GenericUnaryOpStub expects the argument to be in a0.
|
||||||
VisitForAccumulatorValue(expr->expression());
|
VisitForAccumulatorValue(expr->expression());
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
__ mov(a0, result_register());
|
__ mov(a0, result_register());
|
||||||
@ -3929,7 +3929,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
// Record position before stub call.
|
// Record position before stub call.
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE);
|
BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->CountId());
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
|
|
||||||
|
@ -2619,7 +2619,8 @@ int Code::arguments_count() {
|
|||||||
|
|
||||||
int Code::major_key() {
|
int Code::major_key() {
|
||||||
ASSERT(kind() == STUB ||
|
ASSERT(kind() == STUB ||
|
||||||
kind() == TYPE_RECORDING_BINARY_OP_IC ||
|
kind() == UNARY_OP_IC ||
|
||||||
|
kind() == BINARY_OP_IC ||
|
||||||
kind() == COMPARE_IC);
|
kind() == COMPARE_IC);
|
||||||
return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
|
return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
|
||||||
}
|
}
|
||||||
@ -2627,8 +2628,8 @@ int Code::major_key() {
|
|||||||
|
|
||||||
void Code::set_major_key(int major) {
|
void Code::set_major_key(int major) {
|
||||||
ASSERT(kind() == STUB ||
|
ASSERT(kind() == STUB ||
|
||||||
kind() == TYPE_RECORDING_UNARY_OP_IC ||
|
kind() == UNARY_OP_IC ||
|
||||||
kind() == TYPE_RECORDING_BINARY_OP_IC ||
|
kind() == BINARY_OP_IC ||
|
||||||
kind() == COMPARE_IC);
|
kind() == COMPARE_IC);
|
||||||
ASSERT(0 <= major && major < 256);
|
ASSERT(0 <= major && major < 256);
|
||||||
WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
|
WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
|
||||||
@ -2736,38 +2737,38 @@ void Code::set_external_array_type(ExternalArrayType value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte Code::type_recording_unary_op_type() {
|
byte Code::unary_op_type() {
|
||||||
ASSERT(is_type_recording_unary_op_stub());
|
ASSERT(is_unary_op_stub());
|
||||||
return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
|
return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Code::set_type_recording_unary_op_type(byte value) {
|
void Code::set_unary_op_type(byte value) {
|
||||||
ASSERT(is_type_recording_unary_op_stub());
|
ASSERT(is_unary_op_stub());
|
||||||
WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
|
WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte Code::type_recording_binary_op_type() {
|
byte Code::binary_op_type() {
|
||||||
ASSERT(is_type_recording_binary_op_stub());
|
ASSERT(is_binary_op_stub());
|
||||||
return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
|
return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Code::set_type_recording_binary_op_type(byte value) {
|
void Code::set_binary_op_type(byte value) {
|
||||||
ASSERT(is_type_recording_binary_op_stub());
|
ASSERT(is_binary_op_stub());
|
||||||
WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
|
WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte Code::type_recording_binary_op_result_type() {
|
byte Code::binary_op_result_type() {
|
||||||
ASSERT(is_type_recording_binary_op_stub());
|
ASSERT(is_binary_op_stub());
|
||||||
return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
|
return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Code::set_type_recording_binary_op_result_type(byte value) {
|
void Code::set_binary_op_result_type(byte value) {
|
||||||
ASSERT(is_type_recording_binary_op_stub());
|
ASSERT(is_binary_op_stub());
|
||||||
WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
|
WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6591,8 +6591,8 @@ const char* Code::Kind2String(Kind kind) {
|
|||||||
case KEYED_STORE_IC: return "KEYED_STORE_IC";
|
case KEYED_STORE_IC: return "KEYED_STORE_IC";
|
||||||
case CALL_IC: return "CALL_IC";
|
case CALL_IC: return "CALL_IC";
|
||||||
case KEYED_CALL_IC: return "KEYED_CALL_IC";
|
case KEYED_CALL_IC: return "KEYED_CALL_IC";
|
||||||
case TYPE_RECORDING_UNARY_OP_IC: return "TYPE_RECORDING_UNARY_OP_IC";
|
case UNARY_OP_IC: return "UNARY_OP_IC";
|
||||||
case TYPE_RECORDING_BINARY_OP_IC: return "TYPE_RECORDING_BINARY_OP_IC";
|
case BINARY_OP_IC: return "BINARY_OP_IC";
|
||||||
case COMPARE_IC: return "COMPARE_IC";
|
case COMPARE_IC: return "COMPARE_IC";
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -3306,8 +3306,8 @@ class Code: public HeapObject {
|
|||||||
KEYED_CALL_IC,
|
KEYED_CALL_IC,
|
||||||
STORE_IC,
|
STORE_IC,
|
||||||
KEYED_STORE_IC,
|
KEYED_STORE_IC,
|
||||||
TYPE_RECORDING_UNARY_OP_IC,
|
UNARY_OP_IC,
|
||||||
TYPE_RECORDING_BINARY_OP_IC,
|
BINARY_OP_IC,
|
||||||
COMPARE_IC,
|
COMPARE_IC,
|
||||||
// No more than 16 kinds. The value currently encoded in four bits in
|
// No more than 16 kinds. The value currently encoded in four bits in
|
||||||
// Flags.
|
// Flags.
|
||||||
@ -3381,11 +3381,11 @@ class Code: public HeapObject {
|
|||||||
inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
|
inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
|
||||||
inline bool is_call_stub() { return kind() == CALL_IC; }
|
inline bool is_call_stub() { return kind() == CALL_IC; }
|
||||||
inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
|
inline bool is_keyed_call_stub() { return kind() == KEYED_CALL_IC; }
|
||||||
inline bool is_type_recording_unary_op_stub() {
|
inline bool is_unary_op_stub() {
|
||||||
return kind() == TYPE_RECORDING_UNARY_OP_IC;
|
return kind() == UNARY_OP_IC;
|
||||||
}
|
}
|
||||||
inline bool is_type_recording_binary_op_stub() {
|
inline bool is_binary_op_stub() {
|
||||||
return kind() == TYPE_RECORDING_BINARY_OP_IC;
|
return kind() == BINARY_OP_IC;
|
||||||
}
|
}
|
||||||
inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
|
inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
|
||||||
|
|
||||||
@ -3435,15 +3435,15 @@ class Code: public HeapObject {
|
|||||||
inline ExternalArrayType external_array_type();
|
inline ExternalArrayType external_array_type();
|
||||||
inline void set_external_array_type(ExternalArrayType value);
|
inline void set_external_array_type(ExternalArrayType value);
|
||||||
|
|
||||||
// [type-recording unary op type]: For all TYPE_RECORDING_UNARY_OP_IC.
|
// [type-recording unary op type]: For all UNARY_OP_IC.
|
||||||
inline byte type_recording_unary_op_type();
|
inline byte unary_op_type();
|
||||||
inline void set_type_recording_unary_op_type(byte value);
|
inline void set_unary_op_type(byte value);
|
||||||
|
|
||||||
// [type-recording binary op type]: For all TYPE_RECORDING_BINARY_OP_IC.
|
// [type-recording binary op type]: For all TYPE_RECORDING_BINARY_OP_IC.
|
||||||
inline byte type_recording_binary_op_type();
|
inline byte binary_op_type();
|
||||||
inline void set_type_recording_binary_op_type(byte value);
|
inline void set_binary_op_type(byte value);
|
||||||
inline byte type_recording_binary_op_result_type();
|
inline byte binary_op_result_type();
|
||||||
inline void set_type_recording_binary_op_result_type(byte value);
|
inline void set_binary_op_result_type(byte value);
|
||||||
|
|
||||||
// [compare state]: For kind compare IC stubs, tells what state the
|
// [compare state]: For kind compare IC stubs, tells what state the
|
||||||
// stub is in.
|
// stub is in.
|
||||||
|
@ -1568,8 +1568,8 @@ static void ReportCodeKindStatistics() {
|
|||||||
CASE(KEYED_STORE_IC);
|
CASE(KEYED_STORE_IC);
|
||||||
CASE(CALL_IC);
|
CASE(CALL_IC);
|
||||||
CASE(KEYED_CALL_IC);
|
CASE(KEYED_CALL_IC);
|
||||||
CASE(TYPE_RECORDING_UNARY_OP_IC);
|
CASE(UNARY_OP_IC);
|
||||||
CASE(TYPE_RECORDING_BINARY_OP_IC);
|
CASE(BINARY_OP_IC);
|
||||||
CASE(COMPARE_IC);
|
CASE(COMPARE_IC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,13 +258,13 @@ TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) {
|
|||||||
TypeInfo unknown = TypeInfo::Unknown();
|
TypeInfo unknown = TypeInfo::Unknown();
|
||||||
if (!object->IsCode()) return unknown;
|
if (!object->IsCode()) return unknown;
|
||||||
Handle<Code> code = Handle<Code>::cast(object);
|
Handle<Code> code = Handle<Code>::cast(object);
|
||||||
ASSERT(code->is_type_recording_unary_op_stub());
|
ASSERT(code->is_unary_op_stub());
|
||||||
TRUnaryOpIC::TypeInfo type = static_cast<TRUnaryOpIC::TypeInfo>(
|
UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>(
|
||||||
code->type_recording_unary_op_type());
|
code->unary_op_type());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TRUnaryOpIC::SMI:
|
case UnaryOpIC::SMI:
|
||||||
return TypeInfo::Smi();
|
return TypeInfo::Smi();
|
||||||
case TRUnaryOpIC::HEAP_NUMBER:
|
case UnaryOpIC::HEAP_NUMBER:
|
||||||
return TypeInfo::Double();
|
return TypeInfo::Double();
|
||||||
default:
|
default:
|
||||||
return unknown;
|
return unknown;
|
||||||
@ -277,41 +277,41 @@ TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) {
|
|||||||
TypeInfo unknown = TypeInfo::Unknown();
|
TypeInfo unknown = TypeInfo::Unknown();
|
||||||
if (!object->IsCode()) return unknown;
|
if (!object->IsCode()) return unknown;
|
||||||
Handle<Code> code = Handle<Code>::cast(object);
|
Handle<Code> code = Handle<Code>::cast(object);
|
||||||
if (code->is_type_recording_binary_op_stub()) {
|
if (code->is_binary_op_stub()) {
|
||||||
TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>(
|
BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
|
||||||
code->type_recording_binary_op_type());
|
code->binary_op_type());
|
||||||
TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>(
|
BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>(
|
||||||
code->type_recording_binary_op_result_type());
|
code->binary_op_result_type());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
// Uninitialized means never executed.
|
// Uninitialized means never executed.
|
||||||
// TODO(fschneider): Introduce a separate value for never-executed ICs
|
// TODO(fschneider): Introduce a separate value for never-executed ICs
|
||||||
return unknown;
|
return unknown;
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
switch (result_type) {
|
switch (result_type) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
return TypeInfo::Smi();
|
return TypeInfo::Smi();
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
return TypeInfo::Integer32();
|
return TypeInfo::Integer32();
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
return TypeInfo::Double();
|
return TypeInfo::Double();
|
||||||
default:
|
default:
|
||||||
return unknown;
|
return unknown;
|
||||||
}
|
}
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
if (expr->op() == Token::DIV ||
|
if (expr->op() == Token::DIV ||
|
||||||
result_type == TRBinaryOpIC::HEAP_NUMBER) {
|
result_type == BinaryOpIC::HEAP_NUMBER) {
|
||||||
return TypeInfo::Double();
|
return TypeInfo::Double();
|
||||||
}
|
}
|
||||||
return TypeInfo::Integer32();
|
return TypeInfo::Integer32();
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
return TypeInfo::Double();
|
return TypeInfo::Double();
|
||||||
case TRBinaryOpIC::BOTH_STRING:
|
case BinaryOpIC::BOTH_STRING:
|
||||||
return TypeInfo::String();
|
return TypeInfo::String();
|
||||||
case TRBinaryOpIC::STRING:
|
case BinaryOpIC::STRING:
|
||||||
case TRBinaryOpIC::GENERIC:
|
case BinaryOpIC::GENERIC:
|
||||||
return unknown;
|
return unknown;
|
||||||
default:
|
default:
|
||||||
return unknown;
|
return unknown;
|
||||||
@ -353,21 +353,21 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
|
|||||||
TypeInfo unknown = TypeInfo::Unknown();
|
TypeInfo unknown = TypeInfo::Unknown();
|
||||||
if (!object->IsCode()) return unknown;
|
if (!object->IsCode()) return unknown;
|
||||||
Handle<Code> code = Handle<Code>::cast(object);
|
Handle<Code> code = Handle<Code>::cast(object);
|
||||||
if (!code->is_type_recording_binary_op_stub()) return unknown;
|
if (!code->is_binary_op_stub()) return unknown;
|
||||||
|
|
||||||
TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>(
|
BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
|
||||||
code->type_recording_binary_op_type());
|
code->binary_op_type());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
return TypeInfo::Smi();
|
return TypeInfo::Smi();
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
return TypeInfo::Integer32();
|
return TypeInfo::Integer32();
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
return TypeInfo::Double();
|
return TypeInfo::Double();
|
||||||
case TRBinaryOpIC::BOTH_STRING:
|
case BinaryOpIC::BOTH_STRING:
|
||||||
case TRBinaryOpIC::STRING:
|
case BinaryOpIC::STRING:
|
||||||
case TRBinaryOpIC::GENERIC:
|
case BinaryOpIC::GENERIC:
|
||||||
return unknown;
|
return unknown;
|
||||||
default:
|
default:
|
||||||
return unknown;
|
return unknown;
|
||||||
@ -441,8 +441,8 @@ void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
|
|||||||
InlineCacheState state = target->ic_state();
|
InlineCacheState state = target->ic_state();
|
||||||
Code::Kind kind = target->kind();
|
Code::Kind kind = target->kind();
|
||||||
|
|
||||||
if (kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
|
if (kind == Code::BINARY_OP_IC ||
|
||||||
kind == Code::TYPE_RECORDING_UNARY_OP_IC ||
|
kind == Code::UNARY_OP_IC ||
|
||||||
kind == Code::COMPARE_IC) {
|
kind == Code::COMPARE_IC) {
|
||||||
SetInfo(id, target);
|
SetInfo(id, target);
|
||||||
} else if (state == MONOMORPHIC) {
|
} else if (state == MONOMORPHIC) {
|
||||||
@ -484,9 +484,9 @@ void TypeFeedbackOracle::CollectIds(Code* code,
|
|||||||
if (target->is_inline_cache_stub()) {
|
if (target->is_inline_cache_stub()) {
|
||||||
InlineCacheState state = target->ic_state();
|
InlineCacheState state = target->ic_state();
|
||||||
Code::Kind kind = target->kind();
|
Code::Kind kind = target->kind();
|
||||||
if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) {
|
if (kind == Code::BINARY_OP_IC) {
|
||||||
if (target->type_recording_binary_op_type() ==
|
if (target->binary_op_type() ==
|
||||||
TRBinaryOpIC::GENERIC) {
|
BinaryOpIC::GENERIC) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (kind == Code::COMPARE_IC) {
|
} else if (kind == Code::COMPARE_IC) {
|
||||||
|
@ -406,32 +406,31 @@ void IntegerConvert(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingUnaryOpStub(int key,
|
Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
|
||||||
TRUnaryOpIC::TypeInfo type_info) {
|
UnaryOpStub stub(key, type_info);
|
||||||
TypeRecordingUnaryOpStub stub(key, type_info);
|
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) {
|
void UnaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operand_type_) {
|
switch (operand_type_) {
|
||||||
case TRUnaryOpIC::UNINITIALIZED:
|
case UnaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::SMI:
|
case UnaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::HEAP_NUMBER:
|
case UnaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRUnaryOpIC::GENERIC:
|
case UnaryOpIC::GENERIC:
|
||||||
GenerateGenericStub(masm);
|
GenerateGenericStub(masm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
__ pop(rcx); // Save return address.
|
__ pop(rcx); // Save return address.
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
// Left and right arguments are now on top.
|
// Left and right arguments are now on top.
|
||||||
@ -446,7 +445,7 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
// Patch the caller to an appropriate specialized stub and return the
|
// Patch the caller to an appropriate specialized stub and return the
|
||||||
// operation result to the caller of the stub.
|
// operation result to the caller of the stub.
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kUnaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
4,
|
4,
|
||||||
1);
|
1);
|
||||||
@ -454,7 +453,7 @@ void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateSmiStubSub(masm);
|
GenerateSmiStubSub(masm);
|
||||||
@ -468,7 +467,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
||||||
Label slow;
|
Label slow;
|
||||||
GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
|
GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
@ -476,7 +475,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi;
|
Label non_smi;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -484,11 +483,11 @@ void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
||||||
Label* non_smi,
|
Label* non_smi,
|
||||||
Label* slow,
|
Label* slow,
|
||||||
Label::Distance non_smi_near,
|
Label::Distance non_smi_near,
|
||||||
Label::Distance slow_near) {
|
Label::Distance slow_near) {
|
||||||
Label done;
|
Label done;
|
||||||
__ JumpIfNotSmi(rax, non_smi, non_smi_near);
|
__ JumpIfNotSmi(rax, non_smi, non_smi_near);
|
||||||
__ SmiNeg(rax, rax, &done, Label::kNear);
|
__ SmiNeg(rax, rax, &done, Label::kNear);
|
||||||
@ -498,10 +497,9 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(
|
void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
|
||||||
MacroAssembler* masm,
|
Label* non_smi,
|
||||||
Label* non_smi,
|
Label::Distance non_smi_near) {
|
||||||
Label::Distance non_smi_near) {
|
|
||||||
__ JumpIfNotSmi(rax, non_smi, non_smi_near);
|
__ JumpIfNotSmi(rax, non_smi, non_smi_near);
|
||||||
__ SmiNot(rax, rax);
|
__ SmiNot(rax, rax);
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
@ -509,7 +507,7 @@ void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateHeapNumberStubSub(masm);
|
GenerateHeapNumberStubSub(masm);
|
||||||
@ -523,7 +521,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow, call_builtin;
|
Label non_smi, slow, call_builtin;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
|
GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -535,7 +533,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
void UnaryOpStub::GenerateHeapNumberStubBitNot(
|
||||||
MacroAssembler* masm) {
|
MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||||
@ -546,8 +544,8 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
||||||
Label* slow) {
|
Label* slow) {
|
||||||
// Check if the operand is a heap number.
|
// Check if the operand is a heap number.
|
||||||
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
||||||
Heap::kHeapNumberMapRootIndex);
|
Heap::kHeapNumberMapRootIndex);
|
||||||
@ -587,9 +585,8 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
|
||||||
MacroAssembler* masm,
|
Label* slow) {
|
||||||
Label* slow) {
|
|
||||||
// Check if the operand is a heap number.
|
// Check if the operand is a heap number.
|
||||||
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
||||||
Heap::kHeapNumberMapRootIndex);
|
Heap::kHeapNumberMapRootIndex);
|
||||||
@ -606,7 +603,7 @@ void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot(
|
|||||||
|
|
||||||
|
|
||||||
// TODO(svenpanne): Use virtual functions instead of switch.
|
// TODO(svenpanne): Use virtual functions instead of switch.
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
GenerateGenericStubSub(masm);
|
GenerateGenericStubSub(masm);
|
||||||
@ -620,7 +617,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
|
GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -630,7 +627,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
||||||
Label non_smi, slow;
|
Label non_smi, slow;
|
||||||
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
|
||||||
__ bind(&non_smi);
|
__ bind(&non_smi);
|
||||||
@ -640,8 +637,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
|
||||||
MacroAssembler* masm) {
|
|
||||||
// Handle the slow case by jumping to the JavaScript builtin.
|
// Handle the slow case by jumping to the JavaScript builtin.
|
||||||
__ pop(rcx); // pop return address
|
__ pop(rcx); // pop return address
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
@ -659,7 +655,7 @@ void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingUnaryOpStub::GetName() {
|
const char* UnaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -673,23 +669,23 @@ const char* TypeRecordingUnaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingUnaryOpStub_%s_%s_%s",
|
"UnaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
|
Handle<Code> GetBinaryOpStub(int key,
|
||||||
TRBinaryOpIC::TypeInfo type_info,
|
BinaryOpIC::TypeInfo type_info,
|
||||||
TRBinaryOpIC::TypeInfo result_type_info) {
|
BinaryOpIC::TypeInfo result_type_info) {
|
||||||
TypeRecordingBinaryOpStub stub(key, type_info, result_type_info);
|
BinaryOpStub stub(key, type_info, result_type_info);
|
||||||
return stub.GetCode();
|
return stub.GetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||||
__ pop(rcx); // Save return address.
|
__ pop(rcx); // Save return address.
|
||||||
__ push(rdx);
|
__ push(rdx);
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
@ -705,39 +701,39 @@ void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
|||||||
// Patch the caller to an appropriate specialized stub and return the
|
// Patch the caller to an appropriate specialized stub and return the
|
||||||
// operation result to the caller of the stub.
|
// operation result to the caller of the stub.
|
||||||
__ TailCallExternalReference(
|
__ TailCallExternalReference(
|
||||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch),
|
ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
|
||||||
masm->isolate()),
|
masm->isolate()),
|
||||||
5,
|
5,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
void BinaryOpStub::Generate(MacroAssembler* masm) {
|
||||||
switch (operands_type_) {
|
switch (operands_type_) {
|
||||||
case TRBinaryOpIC::UNINITIALIZED:
|
case BinaryOpIC::UNINITIALIZED:
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::SMI:
|
case BinaryOpIC::SMI:
|
||||||
GenerateSmiStub(masm);
|
GenerateSmiStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::INT32:
|
case BinaryOpIC::INT32:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
// The int32 case is identical to the Smi case. We avoid creating this
|
// The int32 case is identical to the Smi case. We avoid creating this
|
||||||
// ic state on x64.
|
// ic state on x64.
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::HEAP_NUMBER:
|
case BinaryOpIC::HEAP_NUMBER:
|
||||||
GenerateHeapNumberStub(masm);
|
GenerateHeapNumberStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::ODDBALL:
|
case BinaryOpIC::ODDBALL:
|
||||||
GenerateOddballStub(masm);
|
GenerateOddballStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::BOTH_STRING:
|
case BinaryOpIC::BOTH_STRING:
|
||||||
GenerateBothStringStub(masm);
|
GenerateBothStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::STRING:
|
case BinaryOpIC::STRING:
|
||||||
GenerateStringStub(masm);
|
GenerateStringStub(masm);
|
||||||
break;
|
break;
|
||||||
case TRBinaryOpIC::GENERIC:
|
case BinaryOpIC::GENERIC:
|
||||||
GenerateGeneric(masm);
|
GenerateGeneric(masm);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -746,7 +742,7 @@ void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* TypeRecordingBinaryOpStub::GetName() {
|
const char* BinaryOpStub::GetName() {
|
||||||
if (name_ != NULL) return name_;
|
if (name_ != NULL) return name_;
|
||||||
const int kMaxNameLength = 100;
|
const int kMaxNameLength = 100;
|
||||||
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
|
||||||
@ -762,19 +758,20 @@ const char* TypeRecordingBinaryOpStub::GetName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||||
"TypeRecordingBinaryOpStub_%s_%s_%s",
|
"BinaryOpStub_%s_%s_%s",
|
||||||
op_name,
|
op_name,
|
||||||
overwrite_name,
|
overwrite_name,
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
void BinaryOpStub::GenerateSmiCode(
|
||||||
|
MacroAssembler* masm,
|
||||||
Label* slow,
|
Label* slow,
|
||||||
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
||||||
|
|
||||||
// Arguments to TypeRecordingBinaryOpStub are in rdx and rax.
|
// Arguments to BinaryOpStub are in rdx and rax.
|
||||||
Register left = rdx;
|
Register left = rdx;
|
||||||
Register right = rax;
|
Register right = rax;
|
||||||
|
|
||||||
@ -920,10 +917,9 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateFloatingPointCode(
|
void BinaryOpStub::GenerateFloatingPointCode(MacroAssembler* masm,
|
||||||
MacroAssembler* masm,
|
Label* allocation_failure,
|
||||||
Label* allocation_failure,
|
Label* non_numeric_failure) {
|
||||||
Label* non_numeric_failure) {
|
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::ADD:
|
case Token::ADD:
|
||||||
case Token::SUB:
|
case Token::SUB:
|
||||||
@ -1022,12 +1018,12 @@ void TypeRecordingBinaryOpStub::GenerateFloatingPointCode(
|
|||||||
// No fall-through from this generated code.
|
// No fall-through from this generated code.
|
||||||
if (FLAG_debug_code) {
|
if (FLAG_debug_code) {
|
||||||
__ Abort("Unexpected fall-through in "
|
__ Abort("Unexpected fall-through in "
|
||||||
"TypeRecordingBinaryStub::GenerateFloatingPointCode.");
|
"BinaryStub::GenerateFloatingPointCode.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
Label left_not_string, call_runtime;
|
Label left_not_string, call_runtime;
|
||||||
|
|
||||||
@ -1058,7 +1054,7 @@ void TypeRecordingBinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateCallRuntimeCode(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateCallRuntimeCode(MacroAssembler* masm) {
|
||||||
GenerateRegisterArgsPush(masm);
|
GenerateRegisterArgsPush(masm);
|
||||||
switch (op_) {
|
switch (op_) {
|
||||||
case Token::ADD:
|
case Token::ADD:
|
||||||
@ -1100,10 +1096,10 @@ void TypeRecordingBinaryOpStub::GenerateCallRuntimeCode(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
|
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
|
||||||
result_type_ == TRBinaryOpIC::SMI) {
|
result_type_ == BinaryOpIC::SMI) {
|
||||||
// Only allow smi results.
|
// Only allow smi results.
|
||||||
GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS);
|
||||||
} else {
|
} else {
|
||||||
@ -1123,19 +1119,19 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::STRING);
|
ASSERT(operands_type_ == BinaryOpIC::STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
GenerateStringAddCode(masm);
|
GenerateStringAddCode(masm);
|
||||||
// Try to add arguments as strings, otherwise, transition to the generic
|
// Try to add arguments as strings, otherwise, transition to the generic
|
||||||
// TRBinaryOpIC type.
|
// BinaryOpIC type.
|
||||||
GenerateTypeTransition(masm);
|
GenerateTypeTransition(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING);
|
ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
|
||||||
ASSERT(op_ == Token::ADD);
|
ASSERT(op_ == Token::ADD);
|
||||||
// If both arguments are strings, call the string add stub.
|
// If both arguments are strings, call the string add stub.
|
||||||
// Otherwise, do a transition.
|
// Otherwise, do a transition.
|
||||||
@ -1163,7 +1159,7 @@ void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
||||||
Label call_runtime;
|
Label call_runtime;
|
||||||
|
|
||||||
if (op_ == Token::ADD) {
|
if (op_ == Token::ADD) {
|
||||||
@ -1196,7 +1192,7 @@ void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||||
Label gc_required, not_number;
|
Label gc_required, not_number;
|
||||||
GenerateFloatingPointCode(masm, &gc_required, ¬_number);
|
GenerateFloatingPointCode(masm, &gc_required, ¬_number);
|
||||||
|
|
||||||
@ -1208,7 +1204,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
||||||
Label call_runtime, call_string_add_or_runtime;
|
Label call_runtime, call_string_add_or_runtime;
|
||||||
|
|
||||||
GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
||||||
@ -1225,9 +1221,8 @@ void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
void BinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
|
||||||
MacroAssembler* masm,
|
Label* alloc_failure) {
|
||||||
Label* alloc_failure) {
|
|
||||||
Label skip_allocation;
|
Label skip_allocation;
|
||||||
OverwriteMode mode = mode_;
|
OverwriteMode mode = mode_;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@ -1265,7 +1260,7 @@ void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
||||||
__ pop(rcx);
|
__ pop(rcx);
|
||||||
__ push(rdx);
|
__ push(rdx);
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
|
@ -71,18 +71,18 @@ class ToBooleanStub: public CodeStub {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingUnaryOpStub: public CodeStub {
|
class UnaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingUnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
UnaryOpStub(Token::Value op, UnaryOverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operand_type_(TRUnaryOpIC::UNINITIALIZED),
|
operand_type_(UnaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingUnaryOpStub(
|
UnaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRUnaryOpIC::TypeInfo operand_type)
|
UnaryOpIC::TypeInfo operand_type)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
operand_type_(operand_type),
|
operand_type_(operand_type),
|
||||||
@ -94,7 +94,7 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
UnaryOverwriteMode mode_;
|
UnaryOverwriteMode mode_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRUnaryOpIC::TypeInfo operand_type_;
|
UnaryOpIC::TypeInfo operand_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -102,20 +102,20 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingUnaryOpStub %d (op %s), "
|
PrintF("UnaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRUnaryOpIC::GetName(operand_type_));
|
UnaryOpIC::GetName(operand_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
|
||||||
class OpBits: public BitField<Token::Value, 1, 7> {};
|
class OpBits: public BitField<Token::Value, 1, 7> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRUnaryOpIC::TypeInfo, 8, 3> {};
|
class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingUnaryOp; }
|
Major MajorKey() { return UnaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return ModeBits::encode(mode_)
|
return ModeBits::encode(mode_)
|
||||||
| OpBits::encode(op_)
|
| OpBits::encode(op_)
|
||||||
@ -151,33 +151,33 @@ class TypeRecordingUnaryOpStub: public CodeStub {
|
|||||||
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
void GenerateGenericStubBitNot(MacroAssembler* masm);
|
||||||
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
void GenerateGenericCodeFallback(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_UNARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRUnaryOpIC::ToState(operand_type_);
|
return UnaryOpIC::ToState(operand_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_unary_op_type(operand_type_);
|
code->set_unary_op_type(operand_type_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TypeRecordingBinaryOpStub: public CodeStub {
|
class BinaryOpStub: public CodeStub {
|
||||||
public:
|
public:
|
||||||
TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
|
BinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||||
: op_(op),
|
: op_(op),
|
||||||
mode_(mode),
|
mode_(mode),
|
||||||
operands_type_(TRBinaryOpIC::UNINITIALIZED),
|
operands_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
result_type_(TRBinaryOpIC::UNINITIALIZED),
|
result_type_(BinaryOpIC::UNINITIALIZED),
|
||||||
name_(NULL) {
|
name_(NULL) {
|
||||||
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub(
|
BinaryOpStub(
|
||||||
int key,
|
int key,
|
||||||
TRBinaryOpIC::TypeInfo operands_type,
|
BinaryOpIC::TypeInfo operands_type,
|
||||||
TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
|
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
|
||||||
: op_(OpBits::decode(key)),
|
: op_(OpBits::decode(key)),
|
||||||
mode_(ModeBits::decode(key)),
|
mode_(ModeBits::decode(key)),
|
||||||
operands_type_(operands_type),
|
operands_type_(operands_type),
|
||||||
@ -194,8 +194,8 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
OverwriteMode mode_;
|
OverwriteMode mode_;
|
||||||
|
|
||||||
// Operand type information determined at runtime.
|
// Operand type information determined at runtime.
|
||||||
TRBinaryOpIC::TypeInfo operands_type_;
|
BinaryOpIC::TypeInfo operands_type_;
|
||||||
TRBinaryOpIC::TypeInfo result_type_;
|
BinaryOpIC::TypeInfo result_type_;
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
@ -203,22 +203,22 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print() {
|
void Print() {
|
||||||
PrintF("TypeRecordingBinaryOpStub %d (op %s), "
|
PrintF("BinaryOpStub %d (op %s), "
|
||||||
"(mode %d, runtime_type_info %s)\n",
|
"(mode %d, runtime_type_info %s)\n",
|
||||||
MinorKey(),
|
MinorKey(),
|
||||||
Token::String(op_),
|
Token::String(op_),
|
||||||
static_cast<int>(mode_),
|
static_cast<int>(mode_),
|
||||||
TRBinaryOpIC::GetName(operands_type_));
|
BinaryOpIC::GetName(operands_type_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Minor key encoding in 15 bits RRRTTTOOOOOOOMM.
|
// Minor key encoding in 15 bits RRRTTTOOOOOOOMM.
|
||||||
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
||||||
class OpBits: public BitField<Token::Value, 2, 7> {};
|
class OpBits: public BitField<Token::Value, 2, 7> {};
|
||||||
class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 9, 3> {};
|
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 9, 3> {};
|
||||||
class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 12, 3> {};
|
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 12, 3> {};
|
||||||
|
|
||||||
Major MajorKey() { return TypeRecordingBinaryOp; }
|
Major MajorKey() { return BinaryOp; }
|
||||||
int MinorKey() {
|
int MinorKey() {
|
||||||
return OpBits::encode(op_)
|
return OpBits::encode(op_)
|
||||||
| ModeBits::encode(mode_)
|
| ModeBits::encode(mode_)
|
||||||
@ -252,15 +252,15 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
|||||||
void GenerateTypeTransition(MacroAssembler* masm);
|
void GenerateTypeTransition(MacroAssembler* masm);
|
||||||
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
|
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
|
||||||
|
|
||||||
virtual InlineCacheState GetICState() {
|
virtual InlineCacheState GetICState() {
|
||||||
return TRBinaryOpIC::ToState(operands_type_);
|
return BinaryOpIC::ToState(operands_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FinishCode(Code* code) {
|
virtual void FinishCode(Code* code) {
|
||||||
code->set_type_recording_binary_op_type(operands_type_);
|
code->set_binary_op_type(operands_type_);
|
||||||
code->set_type_recording_binary_op_result_type(result_type_);
|
code->set_binary_op_result_type(result_type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CodeGenerator;
|
friend class CodeGenerator;
|
||||||
|
@ -1672,7 +1672,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
|
|
||||||
__ bind(&stub_call);
|
__ bind(&stub_call);
|
||||||
__ movq(rax, rcx);
|
__ movq(rax, rcx);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
EmitCallIC(stub.GetCode(), &patch_site, expr->id());
|
||||||
__ jmp(&done, Label::kNear);
|
__ jmp(&done, Label::kNear);
|
||||||
|
|
||||||
@ -1719,7 +1719,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
|
|||||||
Token::Value op,
|
Token::Value op,
|
||||||
OverwriteMode mode) {
|
OverwriteMode mode) {
|
||||||
__ pop(rdx);
|
__ pop(rdx);
|
||||||
TypeRecordingBinaryOpStub stub(op, mode);
|
BinaryOpStub stub(op, mode);
|
||||||
// NULL signals no inlined smi code.
|
// NULL signals no inlined smi code.
|
||||||
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
EmitCallIC(stub.GetCode(), NULL, expr->id());
|
||||||
context()->Plug(rax);
|
context()->Plug(rax);
|
||||||
@ -3727,8 +3727,8 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
|||||||
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
|
||||||
UnaryOverwriteMode overwrite =
|
UnaryOverwriteMode overwrite =
|
||||||
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
|
||||||
TypeRecordingUnaryOpStub stub(expr->op(), overwrite);
|
UnaryOpStub stub(expr->op(), overwrite);
|
||||||
// TypeRecordingUnaryOpStub expects the argument to be in the
|
// UnaryOpStub expects the argument to be in the
|
||||||
// accumulator register rax.
|
// accumulator register rax.
|
||||||
VisitForAccumulatorValue(expr->expression());
|
VisitForAccumulatorValue(expr->expression());
|
||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
@ -3856,7 +3856,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
SetSourcePosition(expr->position());
|
SetSourcePosition(expr->position());
|
||||||
|
|
||||||
// Call stub for +1/-1.
|
// Call stub for +1/-1.
|
||||||
TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
|
BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
|
||||||
if (expr->op() == Token::INC) {
|
if (expr->op() == Token::INC) {
|
||||||
__ Move(rdx, Smi::FromInt(1));
|
__ Move(rdx, Smi::FromInt(1));
|
||||||
} else {
|
} else {
|
||||||
|
@ -453,7 +453,7 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
|
|||||||
|
|
||||||
// Signal that we don't inline smi code before these stubs in the
|
// Signal that we don't inline smi code before these stubs in the
|
||||||
// optimizing code generator.
|
// optimizing code generator.
|
||||||
if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC ||
|
if (code->kind() == Code::BINARY_OP_IC ||
|
||||||
code->kind() == Code::COMPARE_IC) {
|
code->kind() == Code::COMPARE_IC) {
|
||||||
__ nop();
|
__ nop();
|
||||||
}
|
}
|
||||||
@ -1294,7 +1294,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
|
|||||||
ASSERT(ToRegister(instr->InputAt(1)).is(rax));
|
ASSERT(ToRegister(instr->InputAt(1)).is(rax));
|
||||||
ASSERT(ToRegister(instr->result()).is(rax));
|
ASSERT(ToRegister(instr->result()).is(rax));
|
||||||
|
|
||||||
TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
BinaryOpStub stub(instr->op(), NO_OVERWRITE);
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user