Commit bbef8af1 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Use the HandlerFrontendHeader in most call compilers.

R=ishell@chromium.org

Review URL: https://chromiumcodereview.appspot.com/83753002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18125 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0e95ffdd
......@@ -757,11 +757,11 @@ static void GenerateCallFunction(MacroAssembler* masm,
__ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
const int argc = arguments.immediate();
const int receiver_offset = argc * kPointerSize;
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
__ str(r3, MemOperand(sp, receiver_offset));
}
// Invoke the function.
......@@ -1541,25 +1541,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
}
void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
ASSERT(holder->IsGlobalObject());
// Get the number of arguments.
const int argc = arguments().immediate();
// Get the receiver from the stack.
__ ldr(r0, MemOperand(sp, argc * kPointerSize));
// Check that the maps haven't changed.
__ JumpIfSmi(r0, miss);
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()), r0, holder, r3, r1, r4, name, miss);
}
void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell,
Handle<JSFunction> function,
......@@ -1603,33 +1584,16 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
const int argc = arguments().immediate();
// Get the receiver of the function from the stack into r0.
__ ldr(r0, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(r0, &miss);
// Do the right check and compute the holder register.
Register reg = CheckPrototypes(
IC::CurrentTypeOf(object, isolate()),
r0, holder, r1, r3, r4, name, &miss);
Register reg = HandlerFrontendHeader(
object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged());
GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(Code::FAST, name);
......@@ -1645,31 +1609,16 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
Code::StubType type) {
Label miss;
// Check that function is still array
const int argc = arguments().immediate();
GenerateNameCheck(name, &miss);
Register receiver = r1;
if (cell.is_null()) {
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
// Check that the maps haven't changed.
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()), receiver, holder,
r3, r0, r4, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
site->SetElementsKind(GetInitialFastElementsKind());
Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
const int argc = arguments().immediate();
__ mov(r0, Operand(argc));
__ mov(r2, Operand(site_feedback_cell));
__ mov(r1, Operand(function));
......@@ -1677,8 +1626,7 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
ArrayConstructorStub stub(isolate());
__ TailCallStub(&stub);
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -1692,14 +1640,6 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
// If object is not an array or is observed, bail out to regular call.
if (!object->IsJSArray() ||
!cell.is_null() ||
......@@ -1708,21 +1648,12 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
}
Label miss;
GenerateNameCheck(name, &miss);
Register receiver = r1;
// Get the receiver from the stack
const int argc = arguments().immediate();
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
// Check that the maps haven't changed.
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()), receiver, holder,
r3, r0, r4, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
Register receiver = r0;
Register scratch = r1;
const int argc = arguments().immediate();
if (argc == 0) {
// Nothing to do, just return the length.
__ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
......@@ -1741,20 +1672,20 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
// Check that the elements are in fast mode and writable.
__ CheckMap(elements,
r0,
scratch,
Heap::kFixedArrayMapRootIndex,
&check_double,
DONT_DO_SMI_CHECK);
// Get the array's length into r0 and calculate new length.
__ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ add(r0, r0, Operand(Smi::FromInt(argc)));
// Get the array's length into scratch and calculate new length.
__ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ add(scratch, scratch, Operand(Smi::FromInt(argc)));
// Get the elements' length.
__ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
// Check if we could survive without allocation.
__ cmp(r0, r4);
__ cmp(scratch, r4);
__ b(gt, &attempt_to_grow_elements);
// Check if value is a smi.
......@@ -1762,49 +1693,50 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
__ JumpIfNotSmi(r4, &with_write_barrier);
// Save new length.
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
// Store the value.
// We may need a register containing the address end_elements below,
// so write back the value in end_elements.
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
const int kEndElementsOffset =
FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
__ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
// Check for a smi.
__ Drop(argc + 1);
__ mov(r0, scratch);
__ Ret();
__ bind(&check_double);
// Check that the elements are in fast mode and writable.
__ CheckMap(elements,
r0,
scratch,
Heap::kFixedDoubleArrayMapRootIndex,
&call_builtin,
DONT_DO_SMI_CHECK);
// Get the array's length into r0 and calculate new length.
__ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ add(r0, r0, Operand(Smi::FromInt(argc)));
// Get the array's length into scratch and calculate new length.
__ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ add(scratch, scratch, Operand(Smi::FromInt(argc)));
// Get the elements' length.
__ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
// Check if we could survive without allocation.
__ cmp(r0, r4);
__ cmp(scratch, r4);
__ b(gt, &call_builtin);
__ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
__ StoreNumberToDoubleElements(r4, r0, elements, r5, d0,
__ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0,
&call_builtin, argc * kDoubleSize);
// Save new length.
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
// Check for a smi.
__ Drop(argc + 1);
__ mov(r0, scratch);
__ Ret();
__ bind(&with_write_barrier);
......@@ -1855,12 +1787,12 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
}
// Save new length.
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
// Store the value.
// We may need a register containing the address end_elements below,
// so write back the value in end_elements.
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
__ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
__ RecordWrite(elements,
......@@ -1871,10 +1803,11 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
__ Drop(argc + 1);
__ mov(r0, scratch);
__ Ret();
__ bind(&attempt_to_grow_elements);
// r0: array's length + 1.
// scratch: array's length + 1.
if (!FLAG_inline_new) {
__ b(&call_builtin);
......@@ -1896,7 +1829,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
const int kAllocationDelta = 4;
// Load top and check if it is the end of elements.
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
__ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
__ add(end_elements, end_elements, Operand(kEndElementsOffset));
__ mov(r4, Operand(new_space_allocation_top));
__ ldr(r3, MemOperand(r4));
......@@ -1921,13 +1854,14 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
}
// Update elements' and array's sizes.
__ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
__ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
__ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
__ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
// Elements are in new space, so write barrier is not required.
__ Drop(argc + 1);
__ mov(r0, scratch);
__ Ret();
}
__ bind(&call_builtin);
......@@ -1935,9 +1869,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
}
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -1951,14 +1883,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
// If object is not an array or is observed, bail out to regular call.
if (!object->IsJSArray() ||
!cell.is_null() ||
......@@ -1967,26 +1891,18 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
}
Label miss, return_undefined, call_builtin;
Register receiver = r1;
Register receiver = r0;
Register scratch = r1;
Register elements = r3;
GenerateNameCheck(name, &miss);
// Get the receiver from the stack
const int argc = arguments().immediate();
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
// Check that the maps haven't changed.
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), receiver, holder,
elements, r4, r0, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Get the elements array of the object.
__ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
// Check that the elements are in fast mode and writable.
__ CheckMap(elements,
r0,
scratch,
Heap::kFixedArrayMapRootIndex,
&call_builtin,
DONT_DO_SMI_CHECK);
......@@ -2001,8 +1917,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
// We can't address the last element in one operation. Compute the more
// expensive shift first, and use an offset later on.
__ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4));
__ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
__ cmp(r0, r6);
__ ldr(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
__ cmp(scratch, r6);
__ b(eq, &call_builtin);
// Set the array's length.
......@@ -2010,7 +1926,9 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
// Fill with the hole.
__ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize));
const int argc = arguments().immediate();
__ Drop(argc + 1);
__ mov(r0, scratch);
__ Ret();
__ bind(&return_undefined);
......@@ -2022,9 +1940,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
__ TailCallExternalReference(
ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2038,18 +1954,9 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
// If object is not a string, bail out to regular call.
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
const int argc = arguments().immediate();
Label miss;
Label name_miss;
Label index_out_of_range;
......@@ -2060,22 +1967,13 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
DEFAULT_STRING_STUB)) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
r0,
&miss);
ASSERT(!object.is_identical_to(holder));
Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r0, holder, r1, r3, r4, name, &miss);
Register receiver = r1;
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
Register receiver = r0;
Register index = r4;
Register result = r0;
Register result = r1;
const int argc = arguments().immediate();
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
if (argc > 0) {
__ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
......@@ -2092,6 +1990,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
STRING_INDEX_IS_NUMBER);
generator.GenerateFast(masm());
__ Drop(argc + 1);
__ mov(r0, result);
__ Ret();
StubRuntimeCallHelper call_helper;
......@@ -2122,14 +2021,6 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
// If object is not a string, bail out to regular call.
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
......@@ -2143,24 +2034,13 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
DEFAULT_STRING_STUB)) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
r0,
&miss);
ASSERT(!object.is_identical_to(holder));
Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r0, holder, r1, r3, r4, name, &miss);
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
Register receiver = r0;
Register index = r4;
Register scratch = r3;
Register result = r0;
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
Register result = r1;
if (argc > 0) {
__ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
} else {
......@@ -2177,6 +2057,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
STRING_INDEX_IS_NUMBER);
generator.GenerateFast(masm());
__ Drop(argc + 1);
__ mov(r0, result);
__ Ret();
StubRuntimeCallHelper call_helper;
......@@ -2207,14 +2088,6 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
......@@ -2222,20 +2095,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ ldr(r1, MemOperand(sp, 1 * kPointerSize));
__ JumpIfSmi(r1, &miss);
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()),
r1, holder, r0, r3, r4, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2265,9 +2128,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2281,32 +2142,16 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
Label miss, slow;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ ldr(r1, MemOperand(sp, 1 * kPointerSize));
__ JumpIfSmi(r1, &miss);
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()),
r1, holder, r0, r3, r4, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2375,9 +2220,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2391,31 +2234,16 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- ...
// -- sp[argc * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ ldr(r1, MemOperand(sp, 1 * kPointerSize));
__ JumpIfSmi(r1, &miss);
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()),
r1, holder, r0, r3, r4, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2475,9 +2303,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2549,24 +2375,37 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check) {
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize;
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, receiver_offset));
}
}
Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* miss) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
GenerateNameCheck(name, miss);
Register reg = r0;
// Get the receiver from the stack
const int argc = arguments().immediate();
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
const int receiver_offset = argc * kPointerSize;
__ ldr(r0, MemOperand(sp, receiver_offset));
// Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) {
__ JumpIfSmi(r1, &miss);
__ JumpIfSmi(r0, miss);
}
// Make sure that it's okay not to patch the on stack receiver
......@@ -2574,85 +2413,62 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
switch (check) {
case RECEIVER_MAP_CHECK:
__ IncrementCounter(isolate()->counters()->call_const(), 1, r0, r3);
__ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3);
// Check that the maps haven't changed.
CheckPrototypes(
reg = CheckPrototypes(
IC::CurrentTypeOf(object, isolate()),
r1, holder, r0, r3, r4, name, &miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, argc * kPointerSize));
}
reg, holder, r1, r3, r4, name, miss);
break;
case STRING_CHECK: {
// Check that the object is a string.
__ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
__ b(ge, &miss);
__ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE);
__ b(ge, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r0, holder, r3, r1, r4, name, &miss);
masm(), Context::STRING_FUNCTION_INDEX, r1, miss);
break;
}
case SYMBOL_CHECK: {
// Check that the object is a symbol.
__ CompareObjectType(r1, r1, r3, SYMBOL_TYPE);
__ b(ne, &miss);
__ CompareObjectType(reg, r3, r3, SYMBOL_TYPE);
__ b(ne, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r0, holder, r3, r1, r4, name, &miss);
masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss);
break;
}
case NUMBER_CHECK: {
Label fast;
// Check that the object is a smi or a heap number.
__ JumpIfSmi(r1, &fast);
__ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
__ b(ne, &miss);
__ JumpIfSmi(reg, &fast);
__ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE);
__ b(ne, miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r0, holder, r3, r1, r4, name, &miss);
masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss);
break;
}
case BOOLEAN_CHECK: {
GenerateBooleanCheck(r1, &miss);
GenerateBooleanCheck(reg, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r0, holder, r3, r1, r4, name, &miss);
masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss);
break;
}
}
Label success;
__ b(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
if (check != RECEIVER_MAP_CHECK) {
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
reg = CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
r1, holder, r1, r3, r4, name, miss);
}
__ bind(&success);
return reg;
}
......@@ -2681,8 +2497,11 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code;
}
CompileHandlerFrontend(object, holder, name, check);
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object);
CompileHandlerBackend(function);
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(function);
......@@ -2692,10 +2511,6 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
......@@ -2733,10 +2548,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<PropertyCell> cell,
Handle<JSFunction> function,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -----------------------------------
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name),
......@@ -2746,19 +2557,9 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
}
Label miss;
GenerateNameCheck(name, &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
GenerateGlobalReceiverCheck(object, holder, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
__ str(r3, MemOperand(sp, argc * kPointerSize));
}
PatchGlobalProxy(object);
// Set up the context (function already in r1).
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
......@@ -2777,10 +2578,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
__ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(Code::NORMAL, name);
......
......@@ -1602,26 +1602,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
}
void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
ASSERT(holder->IsGlobalObject());
// Get the number of arguments.
const int argc = arguments().immediate();
// Get the receiver from the stack.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Check that the maps haven't changed.
__ JumpIfSmi(edx, miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, miss);
}
void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell,
Handle<JSFunction> function,
......@@ -1668,27 +1648,10 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(edx, &miss);
// Do the right check and compute the holder register.
Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx,
holder, ebx, eax, edi, name, &miss);
Register reg = HandlerFrontendHeader(
object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateFastPropertyLoad(
masm(), edi, reg, index.is_inobject(holder),
......@@ -1699,12 +1662,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
__ j(not_equal, &miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
}
PatchGlobalProxy(object);
// Invoke the function.
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
......@@ -1713,9 +1671,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(Code::FAST, name);
......@@ -1731,28 +1687,16 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
Code::StubType type) {
Label miss;
// Check that function is still array
const int argc = arguments().immediate();
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
// Get the receiver from the stack.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(edx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
site->SetElementsKind(GetInitialFastElementsKind());
Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
const int argc = arguments().immediate();
__ mov(eax, Immediate(argc));
__ mov(ebx, site_feedback_cell);
__ mov(edi, function);
......@@ -1760,8 +1704,7 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
ArrayConstructorStub stub(isolate());
__ TailCallStub(&stub);
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -1775,14 +1718,6 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// If object is not an array or is observed, bail out to regular call.
if (!object->IsJSArray() ||
!cell.is_null() ||
......@@ -1792,18 +1727,9 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
Label miss;
GenerateNameCheck(name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(edx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
if (argc == 0) {
// Noop, return the length.
__ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
......@@ -2021,8 +1947,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
1);
}
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2036,14 +1961,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// If object is not an array or is observed, bail out to regular call.
if (!object->IsJSArray() ||
!cell.is_null() ||
......@@ -2053,16 +1970,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Label miss, return_undefined, call_builtin;
GenerateNameCheck(name, &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(edx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Get the elements array of the object.
__ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
......@@ -2094,6 +2002,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
ecx, times_half_pointer_size,
FixedArray::kHeaderSize),
Immediate(factory()->the_hole_value()));
const int argc = arguments().immediate();
__ ret((argc + 1) * kPointerSize);
__ bind(&return_undefined);
......@@ -2106,8 +2015,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
argc + 1,
1);
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2121,14 +2029,6 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// If object is not a string, bail out to regular call.
if (!object->IsString() || !cell.is_null()) {
return Handle<Code>::null();
......@@ -2147,18 +2047,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
eax,
&miss);
ASSERT(!object.is_identical_to(holder));
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, &miss);
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
Register receiver = ebx;
Register index = edi;
......@@ -2207,14 +2096,6 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
// If object is not a string, bail out to regular call.
if (!object->IsString() || !cell.is_null()) {
return Handle<Code>::null();
......@@ -2233,18 +2114,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
eax,
&miss);
ASSERT(!object.is_identical_to(holder));
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, &miss);
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
Register receiver = eax;
Register index = edi;
......@@ -2295,14 +2165,6 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
......@@ -2312,18 +2174,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
}
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ mov(edx, Operand(esp, 2 * kPointerSize));
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(edx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2356,9 +2210,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ bind(&miss);
// ecx: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2372,14 +2224,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
if (!CpuFeatures::IsSupported(SSE2)) {
return Handle<Code>::null();
}
......@@ -2395,20 +2239,10 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
}
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ mov(edx, Operand(esp, 2 * kPointerSize));
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(edx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2488,9 +2322,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// ecx: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2504,14 +2336,6 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
......@@ -2521,20 +2345,10 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
}
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ mov(edx, Operand(esp, 2 * kPointerSize));
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(edx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2597,9 +2411,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// ecx: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2676,27 +2488,32 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = (argc + 1) * kPointerSize;
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, receiver_offset), edx);
}
}
Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* miss) {
GenerateNameCheck(name, miss);
Register reg = edx;
// Get the receiver from the stack.
const int argc = arguments().immediate();
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
const int receiver_offset = (argc + 1) * kPointerSize;
__ mov(reg, Operand(esp, receiver_offset));
// Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) {
__ JumpIfSmi(edx, &miss);
__ JumpIfSmi(reg, miss);
}
// Make sure that it's okay not to patch the on stack receiver
......@@ -2707,80 +2524,58 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
__ IncrementCounter(isolate()->counters()->call_const(), 1);
// Check that the maps haven't changed.
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
ebx, eax, edi, name, &miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
}
reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
ebx, eax, edi, name, miss);
break;
case STRING_CHECK: {
// Check that the object is a string.
__ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
__ j(above_equal, &miss);
__ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax);
__ j(above_equal, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, &miss);
masm(), Context::STRING_FUNCTION_INDEX, eax, miss);
break;
}
case SYMBOL_CHECK: {
// Check that the object is a symbol.
__ CmpObjectType(edx, SYMBOL_TYPE, eax);
__ j(not_equal, &miss);
__ CmpObjectType(reg, SYMBOL_TYPE, eax);
__ j(not_equal, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, &miss);
masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss);
break;
}
case NUMBER_CHECK: {
Label fast;
// Check that the object is a smi or a heap number.
__ JumpIfSmi(edx, &fast);
__ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
__ j(not_equal, &miss);
__ JumpIfSmi(reg, &fast);
__ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax);
__ j(not_equal, miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, &miss);
masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss);
break;
}
case BOOLEAN_CHECK: {
GenerateBooleanCheck(edx, &miss);
GenerateBooleanCheck(reg, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, &miss);
masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss);
break;
}
}
Label success;
__ jmp(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
if (check != RECEIVER_MAP_CHECK) {
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
reg = CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
eax, holder, ebx, edx, edi, name, miss);
}
__ bind(&success);
return reg;
}
......@@ -2810,8 +2605,11 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code;
}
CompileHandlerFrontend(object, holder, name, check);
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object);
CompileHandlerBackend(function);
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(function);
......@@ -2821,13 +2619,6 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
......@@ -2883,14 +2674,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<PropertyCell> cell,
Handle<JSFunction> function,
Handle<Name> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- esp[(argc + 1) * 4] : receiver
// -----------------------------------
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name),
......@@ -2900,18 +2683,9 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
}
Label miss;
GenerateNameCheck(name, &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
GenerateGlobalReceiverCheck(object, holder, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
// Patch the receiver on the stack with the global proxy.
if (object->IsGlobalObject()) {
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
}
PatchGlobalProxy(object);
// Set up the context (function already in edi).
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
......@@ -2930,10 +2704,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(Code::NORMAL, name);
......
......@@ -1126,6 +1126,12 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
#define __ ACCESS_MASM(masm())
void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
__ bind(miss);
GenerateMissBranch();
}
Register LoadStubCompiler::HandlerFrontendHeader(
Handle<Type> type,
Register object_reg,
......
......@@ -906,10 +906,17 @@ class CallStubCompiler: public StubCompiler {
PropertyIndex index,
Handle<Name> name);
void CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check);
// Patch the global proxy over the global object if the global object is the
// receiver.
void PatchGlobalProxy(Handle<Object> object);
// Returns the register containing the holder of |name|.
Register HandlerFrontendHeader(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* miss);
void HandlerFrontendFooter(Label* miss);
void CompileHandlerBackend(Handle<JSFunction> function);
......@@ -967,11 +974,6 @@ class CallStubCompiler: public StubCompiler {
void GenerateNameCheck(Handle<Name> name, Label* miss);
void GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss);
// Generates code to load the function from the cell checking that
// it still contains the same function.
void GenerateLoadFunctionFromCell(Handle<Cell> cell,
......
......@@ -1537,23 +1537,6 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
}
void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
Label* miss) {
ASSERT(holder->IsGlobalObject());
StackArgumentsAccessor args(rsp, arguments());
__ movq(rdx, args.GetReceiverOperand());
// Check that the maps haven't changed.
__ JumpIfSmi(rdx, miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, miss);
}
void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell,
Handle<JSFunction> function,
......@@ -1596,28 +1579,10 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
Handle<JSObject> holder,
PropertyIndex index,
Handle<Name> name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
// rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ...
// rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
StackArgumentsAccessor args(rsp, arguments());
__ movq(rdx, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &miss);
// Do the right check and compute the holder register.
Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx,
holder, rbx, rax, rdi, name, &miss);
Register reg = HandlerFrontendHeader(
object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged());
......@@ -1627,12 +1592,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
__ j(not_equal, &miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
}
PatchGlobalProxy(object);
// Invoke the function.
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
......@@ -1641,9 +1601,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(Code::FAST, name);
......@@ -1659,28 +1617,16 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
Code::StubType type) {
Label miss;
// Check that function is still array
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
site->SetElementsKind(GetInitialFastElementsKind());
Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
const int argc = arguments().immediate();
__ movq(rax, Immediate(argc));
__ Move(rbx, site_feedback_cell);
__ Move(rdi, function);
......@@ -1688,8 +1634,7 @@ Handle<Code> CallStubCompiler::CompileArrayCodeCall(
ArrayConstructorStub stub(isolate());
__ TailCallStub(&stub);
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -1719,18 +1664,11 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
}
Label miss;
GenerateNameCheck(name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
__ movq(rdx, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
if (argc == 0) {
// Noop, return the length.
__ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
......@@ -1943,8 +1881,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
1);
}
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -1958,14 +1895,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- ...
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// If object is not an array or is observed, bail out to regular call.
if (!object->IsJSArray() ||
!cell.is_null() ||
......@@ -1974,17 +1903,8 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
}
Label miss, return_undefined, call_builtin;
GenerateNameCheck(name, &miss);
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
__ movq(rdx, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Get the elements array of the object.
__ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
......@@ -2017,6 +1937,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
rcx, times_pointer_size,
FixedArray::kHeaderSize),
r9);
const int argc = arguments().immediate();
__ ret((argc + 1) * kPointerSize);
__ bind(&return_undefined);
......@@ -2029,8 +1950,7 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
argc + 1,
1);
__ bind(&miss);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2044,20 +1964,9 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- ...
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// If object is not a string, bail out to regular call.
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
Label miss;
Label name_miss;
Label index_out_of_range;
......@@ -2067,22 +1976,15 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
DEFAULT_STRING_STUB)) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
rax,
&miss);
ASSERT(!object.is_identical_to(holder));
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, &miss);
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
Register receiver = rbx;
Register index = rdi;
Register result = rax;
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
__ movq(receiver, args.GetReceiverOperand());
if (argc > 0) {
__ movq(index, args.GetArgumentOperand(1));
......@@ -2127,14 +2029,6 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- ...
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// If object is not a string, bail out to regular call.
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
......@@ -2150,18 +2044,8 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
DEFAULT_STRING_STUB)) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
rax,
&miss);
ASSERT(!object.is_identical_to(holder));
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, &miss);
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
Register receiver = rax;
Register index = rdi;
......@@ -2211,14 +2095,6 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- ...
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
const int argc = arguments().immediate();
......@@ -2226,17 +2102,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, args.GetReceiverOperand());
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2268,9 +2137,7 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ bind(&miss);
// rcx: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2284,13 +2151,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
// -- rsp[(argc - n) * 4] : arg[n] (zero-based)
// -- ...
// -- rsp[(argc + 1) * 4] : receiver
// -----------------------------------
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
......@@ -2300,21 +2160,11 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
return Handle<Code>::null();
}
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, args.GetReceiverOperand());
Label miss, slow;
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
......@@ -2327,7 +2177,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ JumpIfSmi(rax, &smi);
// Check if the argument is a heap number and load its value into xmm0.
Label slow;
__ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
__ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
......@@ -2396,9 +2245,7 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// rcx: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2412,14 +2259,6 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<JSFunction> function,
Handle<String> name,
Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- ...
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
const int argc = arguments().immediate();
......@@ -2427,19 +2266,13 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
Label miss;
GenerateNameCheck(name, &miss);
if (cell.is_null()) {
__ movq(rdx, args.GetReceiverOperand());
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
} else {
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
if (!cell.is_null()) {
ASSERT(cell->value() == *function);
GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
&miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
}
// Load the (only) argument into rax.
__ movq(rax, args.GetArgumentOperand(1));
......@@ -2501,9 +2334,7 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
__ InvokeFunction(function, expected, arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ bind(&miss);
// rcx: function name.
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(type, name);
......@@ -2578,28 +2409,30 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
// rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ...
// rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
if (object->IsGlobalObject()) {
StackArgumentsAccessor args(rsp, arguments());
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
}
}
Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
Handle<JSObject> holder,
Handle<Name> name,
CheckType check,
Label* miss) {
GenerateNameCheck(name, miss);
Register reg = rdx;
StackArgumentsAccessor args(rsp, arguments());
__ movq(rdx, args.GetReceiverOperand());
__ movq(reg, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) {
__ JumpIfSmi(rdx, &miss);
__ JumpIfSmi(reg, miss);
}
// Make sure that it's okay not to patch the on stack receiver
......@@ -2612,80 +2445,57 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
__ IncrementCounter(counters->call_const(), 1);
// Check that the maps haven't changed.
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
rbx, rax, rdi, name, &miss);
// Patch the receiver on the stack with the global proxy if
// necessary.
if (object->IsGlobalObject()) {
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
}
reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
rbx, rax, rdi, name, miss);
break;
case STRING_CHECK: {
// Check that the object is a string.
__ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
__ j(above_equal, &miss);
__ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
__ j(above_equal, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, &miss);
masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
break;
}
case SYMBOL_CHECK: {
// Check that the object is a symbol.
__ CmpObjectType(rdx, SYMBOL_TYPE, rax);
__ j(not_equal, &miss);
__ CmpObjectType(reg, SYMBOL_TYPE, rax);
__ j(not_equal, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, &miss);
masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
break;
}
case NUMBER_CHECK: {
Label fast;
// Check that the object is a smi or a heap number.
__ JumpIfSmi(rdx, &fast);
__ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
__ j(not_equal, &miss);
__ JumpIfSmi(reg, &fast);
__ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
__ j(not_equal, miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, &miss);
masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
break;
}
case BOOLEAN_CHECK: {
GenerateBooleanCheck(rdx, &miss);
GenerateBooleanCheck(reg, miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, &miss);
masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
break;
}
}
Label success;
__ jmp(&success);
// Handle call cache miss.
__ bind(&miss);
GenerateMissBranch();
if (check != RECEIVER_MAP_CHECK) {
Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
reg = CheckPrototypes(
IC::CurrentTypeOf(prototype, isolate()),
rax, holder, rbx, rdx, rdi, name, miss);
}
__ bind(&success);
return reg;
}
......@@ -2714,8 +2524,11 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code;
}
CompileHandlerFrontend(object, holder, name, check);
Label miss;
HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object);
CompileHandlerBackend(function);
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(function);
......@@ -2725,19 +2538,9 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
// rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ...
// rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
Label miss;
GenerateNameCheck(name, &miss);
LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup);
......@@ -2787,16 +2590,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<PropertyCell> cell,
Handle<JSFunction> function,
Handle<Name> name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
// rsp[8] : argument argc
// rsp[16] : argument argc - 1
// ...
// rsp[argc * 8] : argument 1
// rsp[(argc + 1) * 8] : argument 0 = receiver
// -----------------------------------
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name),
......@@ -2806,17 +2599,9 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
}
Label miss;
GenerateNameCheck(name, &miss);
StackArgumentsAccessor args(rsp, arguments());
GenerateGlobalReceiverCheck(object, holder, name, &miss);
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateLoadFunctionFromCell(cell, function, &miss);
// Patch the receiver on the stack with the global proxy.
if (object->IsGlobalObject()) {
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
}
PatchGlobalProxy(object);
// Set up the context (function already in rdi).
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
......@@ -2835,10 +2620,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
__ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1);
GenerateMissBranch();
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(Code::NORMAL, name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment