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