[lazy-accessor-pairs] Don't take the fast paths if the context needs to be switched
This works in the ICs since compiled handlers are not shared anymore. As drive-by cleanup I also removed custom code to deal with compiled handler sharing for primitive and access-checked objects. Bug: chromium:759734 Change-Id: Ifb394221c2398f42ea9305acc02845db6004c680 Reviewed-on: https://chromium-review.googlesource.com/738381 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#48979}
This commit is contained in:
parent
b4fdce5ae9
commit
cb84b6f624
@ -1483,7 +1483,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- sp[(argc - 1) * 4] : first argument
|
||||
// -- sp[argc * 4] : receiver
|
||||
// -- sp[(argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = r0;
|
||||
@ -1531,32 +1530,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
__ push(holder);
|
||||
|
||||
// enter a new context
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- sp[0] : holder
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength - 1) * 4] : new_target
|
||||
// -- sp[FCA::kArgsLength * 4] : last argument
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength + argc - 1) * 4] : first argument
|
||||
// -- sp[(FCA::kArgsLength + argc) * 4] : receiver
|
||||
// -- sp[(FCA::kArgsLength + argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
__ ldr(accessor_holder,
|
||||
MemOperand(sp, (FCA::kArgsLength + 1 + argc()) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ ldr(scratch0, FieldMemOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ ldrb(scratch1, FieldMemOperand(scratch0, Map::kBitFieldOffset));
|
||||
__ tst(scratch1, Operand(1 << Map::kIsConstructor));
|
||||
__ b(ne, &skip_looking_for_constructor);
|
||||
__ GetMapConstructor(context, scratch0, scratch0, scratch1);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ ldr(context, FieldMemOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// load context from callee
|
||||
__ ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1599,7 +1573,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
return_value_offset = 2 + FCA::kReturnValueOffset;
|
||||
}
|
||||
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc() + FCA::kArgsLength + 1;
|
||||
MemOperand* stack_space_operand = nullptr;
|
||||
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
|
||||
|
@ -1656,19 +1656,6 @@ void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
|
||||
JumpIfSmi(value, miss);
|
||||
}
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp, Register temp2) {
|
||||
Label done, loop;
|
||||
ldr(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done);
|
||||
CompareObjectType(result, temp, temp2, MAP_TYPE);
|
||||
b(ne, &done);
|
||||
ldr(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
b(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::CallStub(CodeStub* stub,
|
||||
Condition cond) {
|
||||
DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs.
|
||||
|
@ -730,11 +730,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done, and |temp2| its instance type.
|
||||
void GetMapConstructor(Register result, Register map, Register temp,
|
||||
Register temp2);
|
||||
|
||||
// Compare object type for heap object. heap_object contains a non-Smi
|
||||
// whose object type should be compared with the given type. This both
|
||||
// sets the flags and leaves the object type in the type_reg register.
|
||||
|
@ -1706,7 +1706,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- sp[(argc - 1) * 8] : first argument
|
||||
// -- sp[argc * 8] : receiver
|
||||
// -- sp[(argc + 1) * 8] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = x0;
|
||||
@ -1741,35 +1740,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
__ Push(undef, undef, isolate_reg, holder);
|
||||
|
||||
// Enter a new context.
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- sp[0] : holder
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength - 1) * 8] : new_target
|
||||
// -- sp[FCA::kArgsLength * 8] : last argument
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength + argc - 1) * 8] : first argument
|
||||
// -- sp[(FCA::kArgsLength + argc) * 8] : receiver
|
||||
// -- sp[(FCA::kArgsLength + argc + 1) * 8] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// Load context from accessor_holder.
|
||||
Register accessor_holder = context;
|
||||
Register scratch = undef;
|
||||
Register scratch2 = callee;
|
||||
__ Ldr(accessor_holder,
|
||||
MemOperand(__ StackPointer(),
|
||||
(FCA::kArgsLength + 1 + argc()) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ Ldr(scratch, FieldMemOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ Ldrb(scratch2, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
||||
__ Tst(scratch2, Operand(1 << Map::kIsConstructor));
|
||||
__ B(ne, &skip_looking_for_constructor);
|
||||
__ GetMapConstructor(context, scratch, scratch, scratch2);
|
||||
__ Bind(&skip_looking_for_constructor);
|
||||
__ Ldr(context, FieldMemOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// Load context from callee.
|
||||
__ Ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1817,8 +1788,8 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// The number of arguments might be odd, but will be padded when calling the
|
||||
// stub. We do not round up stack_space here, this will be done in
|
||||
// CallApiFunctionAndReturn.
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
DCHECK_EQ((stack_space - argc()) % 2, 0);
|
||||
const int stack_space = (argc() + 1) + FCA::kArgsLength;
|
||||
DCHECK_EQ((stack_space - (argc() + 1)) % 2, 0);
|
||||
const int spill_offset = 1 + kApiStackSpace;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
|
||||
spill_offset, return_value_operand,
|
||||
|
@ -2721,19 +2721,6 @@ void MacroAssembler::LoadElementsKindFromMap(Register result, Register map) {
|
||||
DecodeField<Map::ElementsKindBits>(result);
|
||||
}
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp, Register temp2) {
|
||||
Label done, loop;
|
||||
Ldr(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
Bind(&loop);
|
||||
JumpIfSmi(result, &done);
|
||||
CompareObjectType(result, temp, temp2, MAP_TYPE);
|
||||
B(ne, &done);
|
||||
Ldr(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
B(&loop);
|
||||
Bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::CompareRoot(const Register& obj,
|
||||
Heap::RootListIndex index) {
|
||||
UseScratchRegisterScope temps(this);
|
||||
|
@ -1892,11 +1892,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done, and |temp2| its instance type.
|
||||
void GetMapConstructor(Register result, Register map, Register temp,
|
||||
Register temp2);
|
||||
|
||||
// Compare object type for heap object. heap_object contains a non-Smi
|
||||
// whose object type should be compared with the given type. This both
|
||||
// sets the flags and leaves the object type in the type_reg register.
|
||||
|
@ -445,7 +445,12 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
|
||||
isolate());
|
||||
if (!accessor->IsJSFunction()) {
|
||||
CallOptimization optimization(accessor);
|
||||
if (optimization.IsCrossContextLazyAccessorPair(*native_context_,
|
||||
*map)) {
|
||||
return false;
|
||||
}
|
||||
if (!optimization.is_simple_api_call()) return false;
|
||||
|
||||
CallOptimization::HolderLookup lookup;
|
||||
holder =
|
||||
optimization.LookupHolderOfExpectedType(receiver_map, &lookup);
|
||||
|
@ -1617,8 +1617,7 @@ Reduction JSCallReducer::ReduceCallApiFunction(
|
||||
CallInterfaceDescriptor cid = stub.GetCallInterfaceDescriptor();
|
||||
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), cid,
|
||||
cid.GetStackParameterCount() + argc +
|
||||
2 /* implicit receiver + accessor_holder */,
|
||||
cid.GetStackParameterCount() + argc + 1 /* implicit receiver */,
|
||||
CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
|
||||
MachineType::AnyTagged(), 1);
|
||||
ApiFunction api_function(v8::ToCData<Address>(call_handler_info->callback()));
|
||||
@ -1633,8 +1632,7 @@ Reduction JSCallReducer::ReduceCallApiFunction(
|
||||
node->InsertInput(graph()->zone(), 3, holder);
|
||||
node->InsertInput(graph()->zone(), 4,
|
||||
jsgraph()->ExternalConstant(function_reference));
|
||||
node->InsertInput(graph()->zone(), 5, holder /* as accessor_holder */);
|
||||
node->ReplaceInput(6, receiver);
|
||||
node->ReplaceInput(5, receiver);
|
||||
NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
|
||||
return Changed(node);
|
||||
}
|
||||
|
@ -1700,7 +1700,7 @@ Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), call_interface_descriptor,
|
||||
call_interface_descriptor.GetStackParameterCount() + argc +
|
||||
1 /* implicit receiver */ + 1 /* accessor holder */,
|
||||
1 /* implicit receiver */,
|
||||
CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
|
||||
MachineType::AnyTagged(), 1);
|
||||
|
||||
@ -1712,9 +1712,8 @@ Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
Node* code = jsgraph()->HeapConstant(stub.GetCode());
|
||||
|
||||
// Add CallApiCallbackStub's register argument as well.
|
||||
Node* inputs[12] = {code, target, data, holder, function_reference,
|
||||
holder, receiver};
|
||||
int index = 7 + argc;
|
||||
Node* inputs[11] = {code, target, data, holder, function_reference, receiver};
|
||||
int index = 6 + argc;
|
||||
inputs[index++] = context;
|
||||
inputs[index++] = frame_state;
|
||||
inputs[index++] = *effect;
|
||||
@ -1722,7 +1721,7 @@ Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
// This needs to stay here because of the edge case described in
|
||||
// http://crbug.com/675648.
|
||||
if (value != nullptr) {
|
||||
inputs[7] = value;
|
||||
inputs[6] = value;
|
||||
}
|
||||
|
||||
return *effect = *control =
|
||||
|
@ -1436,7 +1436,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- esp[argc * 4] : first argument
|
||||
// -- esp[(argc + 1) * 4] : receiver
|
||||
// -- esp[(argc + 2) * 4] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = edi;
|
||||
@ -1483,33 +1482,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// enter a new context
|
||||
Register scratch = call_data;
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- esp[0] : holder
|
||||
// -- ...
|
||||
// -- esp[(FCA::kArgsLength - 1) * 4] : new_target
|
||||
// -- esp[FCA::kArgsLength * 4] : last argument
|
||||
// -- ...
|
||||
// -- esp[(FCA::kArgsLength + argc - 1) * 4] : first argument
|
||||
// -- esp[(FCA::kArgsLength + argc) * 4] : receiver
|
||||
// -- esp[(FCA::kArgsLength + argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
Register scratch2 = callee;
|
||||
__ mov(accessor_holder,
|
||||
MemOperand(esp, (argc() + FCA::kArgsLength + 1) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ mov(scratch, FieldOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ test_b(FieldOperand(scratch, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsConstructor));
|
||||
__ j(not_zero, &skip_looking_for_constructor, Label::kNear);
|
||||
__ GetMapConstructor(context, scratch, scratch2);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ mov(context, FieldOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// load context from callee
|
||||
__ mov(context, FieldOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1556,7 +1529,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
return_value_offset = 2 + FCA::kReturnValueOffset;
|
||||
}
|
||||
Operand return_value_operand(ebp, return_value_offset * kPointerSize);
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc() + FCA::kArgsLength + 1;
|
||||
Operand* stack_space_operand = nullptr;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
|
||||
ApiParameterOperand(1), stack_space,
|
||||
|
@ -828,19 +828,6 @@ void MacroAssembler::PopStackHandler() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp) {
|
||||
Label done, loop;
|
||||
mov(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done, Label::kNear);
|
||||
CmpObjectType(result, MAP_TYPE, temp);
|
||||
j(not_equal, &done, Label::kNear);
|
||||
mov(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
jmp(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::CallStub(CodeStub* stub) {
|
||||
DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs.
|
||||
call(stub->GetCode(), RelocInfo::CODE_TARGET);
|
||||
|
@ -589,13 +589,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// Unlink the stack handler on top of the stack from the stack handler chain.
|
||||
void PopStackHandler();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done.
|
||||
void GetMapConstructor(Register result, Register map, Register temp);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Runtime calls
|
||||
|
||||
|
@ -178,7 +178,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
int accessor_index) {
|
||||
DCHECK(accessor_holder != scratch_in);
|
||||
DCHECK(receiver != scratch_in);
|
||||
__ push(accessor_holder);
|
||||
__ push(receiver);
|
||||
// Write the arguments to stack frame.
|
||||
if (is_store) {
|
||||
@ -258,31 +257,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ ldr(scratch1, NativeContextMemOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
__ cmp(scratch1, scratch2);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ b(eq, &done);
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ ldr(scratch1,
|
||||
ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ ldr(scratch2,
|
||||
ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
__ cmp(scratch1, scratch2);
|
||||
}
|
||||
__ b(ne, miss);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -110,7 +110,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
DCHECK(!AreAliased(receiver, scratch));
|
||||
|
||||
MacroAssembler::PushPopQueue queue(masm);
|
||||
queue.Queue(accessor_holder);
|
||||
queue.Queue(receiver);
|
||||
// Write the arguments to the stack frame.
|
||||
if (is_store) {
|
||||
@ -254,31 +253,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ Ldr(scratch1, NativeContextMemOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
__ Cmp(scratch1, scratch2);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ B(eq, &done);
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ Ldr(scratch1,
|
||||
ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ Ldr(scratch2,
|
||||
ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
__ Cmp(scratch1, scratch2);
|
||||
}
|
||||
__ B(ne, miss);
|
||||
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -20,6 +20,14 @@ CallOptimization::CallOptimization(Handle<Object> function) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CallOptimization::IsCrossContextLazyAccessorPair(Context* native_context,
|
||||
Map* holder_map) const {
|
||||
DCHECK(native_context->IsNativeContext());
|
||||
if (is_constant_call()) return false;
|
||||
JSFunction* constructor = JSFunction::cast(holder_map->GetConstructor());
|
||||
return native_context != constructor->context()->native_context();
|
||||
}
|
||||
|
||||
Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
|
||||
Handle<Map> object_map, HolderLookup* holder_lookup) const {
|
||||
DCHECK(is_simple_api_call());
|
||||
|
@ -17,6 +17,9 @@ class CallOptimization BASE_EMBEDDED {
|
||||
public:
|
||||
explicit CallOptimization(Handle<Object> function);
|
||||
|
||||
bool IsCrossContextLazyAccessorPair(Context* native_context,
|
||||
Map* holder_map) const;
|
||||
|
||||
bool is_constant_call() const { return !constant_function_.is_null(); }
|
||||
|
||||
Handle<JSFunction> constant_function() const {
|
||||
|
@ -50,20 +50,6 @@ Handle<Code> PropertyHandlerCompiler::GetCode(Handle<Name> name) {
|
||||
Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
|
||||
Handle<Name> name,
|
||||
Label* miss) {
|
||||
if (map()->IsPrimitiveMap() || map()->IsJSGlobalProxyMap()) {
|
||||
// If the receiver is a global proxy and if we get to this point then
|
||||
// the compile-time (current) native context has access to global proxy's
|
||||
// native context. Since access rights revocation is not supported at all,
|
||||
// we can generate a check that an execution-time native context is either
|
||||
// the same as compile-time native context or has the same access token.
|
||||
Handle<Context> native_context = isolate()->native_context();
|
||||
Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
|
||||
|
||||
bool compare_native_contexts_only = map()->IsPrimitiveMap();
|
||||
GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss,
|
||||
compare_native_contexts_only);
|
||||
}
|
||||
|
||||
// Check that the maps starting from the prototype haven't changed.
|
||||
return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
|
||||
miss);
|
||||
@ -75,12 +61,6 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
|
||||
Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
|
||||
Handle<Name> name,
|
||||
Label* miss) {
|
||||
if (map()->IsJSGlobalProxyMap()) {
|
||||
Handle<Context> native_context = isolate()->native_context();
|
||||
Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
|
||||
GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss, false);
|
||||
}
|
||||
|
||||
return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
|
||||
miss);
|
||||
}
|
||||
@ -115,9 +95,10 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
|
||||
if (V8_UNLIKELY(FLAG_runtime_stats)) {
|
||||
GenerateTailCall(masm(), slow_stub);
|
||||
}
|
||||
Register holder = Frontend(name);
|
||||
Register holder_reg = Frontend(name);
|
||||
GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
|
||||
scratch2(), false, no_reg, holder, accessor_index);
|
||||
scratch2(), false, no_reg, holder_reg,
|
||||
accessor_index);
|
||||
return GetCode(name);
|
||||
}
|
||||
|
||||
@ -138,12 +119,12 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
|
||||
if (V8_UNLIKELY(FLAG_runtime_stats)) {
|
||||
GenerateTailCall(masm(), slow_stub);
|
||||
}
|
||||
Register holder = Frontend(name);
|
||||
Register holder_reg = Frontend(name);
|
||||
if (Descriptor::kPassLastArgsOnStack) {
|
||||
__ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
|
||||
}
|
||||
GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
|
||||
receiver(), scratch2(), true, value(), holder,
|
||||
receiver(), scratch2(), true, value(), holder_reg,
|
||||
accessor_index);
|
||||
return GetCode(name);
|
||||
}
|
||||
|
@ -72,25 +72,12 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
|
||||
Handle<Name> name, Register scratch,
|
||||
Label* miss);
|
||||
|
||||
// Generates check that current native context has the same access rights
|
||||
// as the given |native_context_cell|.
|
||||
// If |compare_native_contexts_only| is true then access check is considered
|
||||
// passed if the execution-time native context is equal to contents of
|
||||
// |native_context_cell|.
|
||||
// If |compare_native_contexts_only| is false then access check is considered
|
||||
// passed if the execution-time native context is equal to contents of
|
||||
// |native_context_cell| or security tokens of both contexts are equal.
|
||||
void GenerateAccessCheck(Handle<WeakCell> native_context_cell,
|
||||
Register scratch1, Register scratch2, Label* miss,
|
||||
bool compare_native_contexts_only);
|
||||
|
||||
// Generates code that verifies that the property holder has not changed
|
||||
// (checking maps of objects in the prototype chain for fast and global
|
||||
// objects or doing negative lookup for slow objects, ensures that the
|
||||
// property cells for global objects are still empty) and checks that the map
|
||||
// of the holder has not changed. If necessary the function also generates
|
||||
// code for security check in case of global object holders. Helps to make
|
||||
// sure that the current IC is still valid.
|
||||
// of the holder has not changed. Helps to make sure that the current IC is
|
||||
// still valid.
|
||||
//
|
||||
// The scratch and holder registers are always clobbered, but the object
|
||||
// register is only clobbered if it the same as the holder register. The
|
||||
|
@ -117,7 +117,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
kPointerSize));
|
||||
}
|
||||
// Write the receiver and arguments to stack frame.
|
||||
__ push(accessor_holder);
|
||||
__ push(receiver);
|
||||
if (is_store) {
|
||||
DCHECK(!AreAliased(receiver, scratch, store_parameter));
|
||||
@ -267,29 +266,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ mov(scratch1, NativeContextOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
__ cmp(scratch1, scratch2);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ j(equal, &done);
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ mov(scratch1, ContextOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ mov(scratch2, ContextOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
__ cmp(scratch1, scratch2);
|
||||
}
|
||||
__ j(not_equal, miss);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
17
src/ic/ic.cc
17
src/ic/ic.cc
@ -782,6 +782,10 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
|
||||
}
|
||||
|
||||
CallOptimization call_optimization(getter);
|
||||
if (call_optimization.IsCrossContextLazyAccessorPair(
|
||||
isolate()->raw_native_context(), holder->map())) {
|
||||
return slow_stub();
|
||||
}
|
||||
if (call_optimization.is_simple_api_call()) {
|
||||
if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
|
||||
!holder->HasFastProperties()) {
|
||||
@ -919,8 +923,8 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup) {
|
||||
DCHECK(accessors->IsAccessorPair());
|
||||
DCHECK(holder->HasFastProperties());
|
||||
DCHECK(!GetHostFunction()->shared()->HasBreakInfo());
|
||||
Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
|
||||
isolate());
|
||||
Handle<Object> getter(AccessorPair::cast(*accessors)->getter(), isolate());
|
||||
|
||||
CallOptimization call_optimization(getter);
|
||||
NamedLoadHandlerCompiler compiler(isolate(), map, holder);
|
||||
DCHECK(call_optimization.is_simple_api_call());
|
||||
@ -1412,6 +1416,10 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
|
||||
return slow_stub();
|
||||
}
|
||||
CallOptimization call_optimization(setter);
|
||||
if (call_optimization.IsCrossContextLazyAccessorPair(
|
||||
isolate()->raw_native_context(), holder->map())) {
|
||||
return slow_stub();
|
||||
}
|
||||
if (call_optimization.is_simple_api_call()) {
|
||||
if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
|
||||
break; // Custom-compiled handler.
|
||||
@ -1419,6 +1427,8 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
|
||||
TRACE_GENERIC_IC("incompatible receiver");
|
||||
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
|
||||
return slow_stub();
|
||||
} else if (setter->IsFunctionTemplateInfo()) {
|
||||
return slow_stub();
|
||||
}
|
||||
break; // Custom-compiled handler.
|
||||
}
|
||||
@ -1513,8 +1523,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup) {
|
||||
}
|
||||
|
||||
DCHECK(accessors->IsAccessorPair());
|
||||
Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
|
||||
isolate());
|
||||
Handle<Object> setter(AccessorPair::cast(*accessors)->setter(), isolate());
|
||||
DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
|
||||
CallOptimization call_optimization(setter);
|
||||
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
|
||||
|
@ -169,7 +169,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
int accessor_index) {
|
||||
DCHECK(accessor_holder != scratch_in);
|
||||
DCHECK(receiver != scratch_in);
|
||||
__ push(accessor_holder);
|
||||
__ push(receiver);
|
||||
// Write the arguments to stack frame.
|
||||
if (is_store) {
|
||||
@ -248,27 +247,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ lw(scratch1, NativeContextMemOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ Branch(&done, eq, scratch1, Operand(scratch2));
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ lw(scratch1, ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ lw(scratch2, ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
}
|
||||
__ Branch(miss, ne, scratch1, Operand(scratch2));
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -169,7 +169,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
int accessor_index) {
|
||||
DCHECK(accessor_holder != scratch_in);
|
||||
DCHECK(receiver != scratch_in);
|
||||
__ push(accessor_holder);
|
||||
__ push(receiver);
|
||||
// Write the arguments to stack frame.
|
||||
if (is_store) {
|
||||
@ -248,27 +247,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ Ld(scratch1, NativeContextMemOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ Branch(&done, eq, scratch1, Operand(scratch2));
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ Ld(scratch1, ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ Ld(scratch2, ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
}
|
||||
__ Branch(miss, ne, scratch1, Operand(scratch2));
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -174,7 +174,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
int accessor_index) {
|
||||
DCHECK(accessor_holder != scratch_in);
|
||||
DCHECK(receiver != scratch_in);
|
||||
__ push(accessor_holder);
|
||||
__ push(receiver);
|
||||
// Write the arguments to stack frame.
|
||||
if (is_store) {
|
||||
@ -254,31 +253,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ LoadP(scratch1, NativeContextMemOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
__ cmp(scratch1, scratch2);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ beq(&done);
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ LoadP(scratch1,
|
||||
ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ LoadP(scratch2,
|
||||
ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
__ cmp(scratch1, scratch2);
|
||||
}
|
||||
__ bne(miss);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -167,7 +167,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
int accessor_index) {
|
||||
DCHECK(accessor_holder != scratch_in);
|
||||
DCHECK(receiver != scratch_in);
|
||||
__ Push(accessor_holder);
|
||||
__ Push(receiver);
|
||||
// Write the arguments to stack frame.
|
||||
if (is_store) {
|
||||
@ -246,31 +245,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ LoadP(scratch1, NativeContextMemOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
__ CmpP(scratch1, scratch2);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ beq(&done);
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ LoadP(scratch1,
|
||||
ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ LoadP(scratch2,
|
||||
ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
__ CmpP(scratch1, scratch2);
|
||||
}
|
||||
__ bne(miss);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -92,10 +92,9 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
int accessor_index) {
|
||||
DCHECK(accessor_holder != scratch);
|
||||
DCHECK(optimization.is_simple_api_call());
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
__ PopReturnAddressTo(scratch);
|
||||
// accessor_holder
|
||||
__ Push(accessor_holder);
|
||||
// receiver
|
||||
__ Push(receiver);
|
||||
// Write the arguments to stack frame.
|
||||
@ -110,7 +109,7 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
// Abi for CallApiCallbackStub.
|
||||
Register callee = rdi;
|
||||
Register data = rbx;
|
||||
Register holder = rcx;
|
||||
Register holder_reg = rcx;
|
||||
Register api_function_address = rdx;
|
||||
scratch = no_reg;
|
||||
|
||||
@ -123,18 +122,17 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
|
||||
optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
|
||||
switch (holder_lookup) {
|
||||
case CallOptimization::kHolderIsReceiver:
|
||||
__ Move(holder, receiver);
|
||||
__ Move(holder_reg, receiver);
|
||||
break;
|
||||
case CallOptimization::kHolderFound:
|
||||
__ movp(holder, FieldOperand(receiver, HeapObject::kMapOffset));
|
||||
__ movp(holder, FieldOperand(holder, Map::kPrototypeOffset));
|
||||
__ movp(holder_reg, FieldOperand(receiver, HeapObject::kMapOffset));
|
||||
__ movp(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
|
||||
break;
|
||||
case CallOptimization::kHolderNotFound:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
Isolate* isolate = masm->isolate();
|
||||
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
|
||||
// Put call data in place.
|
||||
if (api_call_info->data()->IsUndefined(isolate)) {
|
||||
@ -250,29 +248,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||
Label* miss, bool compare_native_contexts_only) {
|
||||
Label done;
|
||||
// Load current native context.
|
||||
__ movp(scratch1, NativeContextOperand());
|
||||
// Load expected native context.
|
||||
__ LoadWeakValue(scratch2, native_context_cell, miss);
|
||||
__ cmpp(scratch1, scratch2);
|
||||
|
||||
if (!compare_native_contexts_only) {
|
||||
__ j(equal, &done);
|
||||
|
||||
// Compare security tokens of current and expected native contexts.
|
||||
__ movp(scratch1, ContextOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
|
||||
__ movp(scratch2, ContextOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
|
||||
__ cmpp(scratch1, scratch2);
|
||||
}
|
||||
__ j(not_equal, miss);
|
||||
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
Register object_reg, Register holder_reg, Register scratch1,
|
||||
Register scratch2, Handle<Name> name, Label* miss) {
|
||||
|
@ -1585,7 +1585,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- sp[(argc - 1)* 4] : first argument
|
||||
// -- sp[argc * 4] : receiver
|
||||
// -- sp[(argc + 1)* 4] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = a0;
|
||||
@ -1621,33 +1620,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
__ Push(scratch, holder);
|
||||
|
||||
// Enter a new context
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- sp[0] : holder
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength - 1) * 4] : new_target
|
||||
// -- sp[FCA::kArgsLength * 4] : last argument
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength + argc - 1) * 4] : first argument
|
||||
// -- sp[(FCA::kArgsLength + argc) * 4] : receiver
|
||||
// -- sp[(FCA::kArgsLength + argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// Load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
Register scratch2 = callee;
|
||||
__ lw(accessor_holder,
|
||||
MemOperand(sp, (FCA::kArgsLength + 1 + argc()) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ lw(scratch, FieldMemOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ lbu(scratch2, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
||||
__ And(scratch2, scratch2, Operand(1 << Map::kIsConstructor));
|
||||
__ Branch(&skip_looking_for_constructor, ne, scratch2, Operand(zero_reg));
|
||||
__ GetMapConstructor(context, scratch, scratch, scratch2);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ lw(context, FieldMemOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// Load context from callee.
|
||||
__ lw(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1689,7 +1662,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
return_value_offset = 2 + FCA::kReturnValueOffset;
|
||||
}
|
||||
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc() + FCA::kArgsLength + 1;
|
||||
// TODO(adamk): Why are we clobbering this immediately?
|
||||
const int32_t stack_space_offset = kInvalidStackOffset;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
|
||||
|
@ -4174,19 +4174,6 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp, Register temp2) {
|
||||
Label done, loop;
|
||||
lw(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done);
|
||||
GetObjectType(result, temp, temp2);
|
||||
Branch(&done, ne, temp2, Operand(MAP_TYPE));
|
||||
lw(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
Branch(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::GetObjectType(Register object,
|
||||
Register map,
|
||||
Register type_reg) {
|
||||
|
@ -1088,11 +1088,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// -------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done, and |temp2| its instance type.
|
||||
void GetMapConstructor(Register result, Register map, Register temp,
|
||||
Register temp2);
|
||||
|
||||
void GetObjectType(Register function,
|
||||
Register map,
|
||||
Register type_reg);
|
||||
|
@ -1587,7 +1587,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- sp[(argc - 1) * 8] : first argument
|
||||
// -- sp[argc * 8] : receiver
|
||||
// -- sp[(argc + 1) * 8] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = a0;
|
||||
@ -1623,33 +1622,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
__ Push(scratch, holder);
|
||||
|
||||
// Enter a new context
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- sp[0] : holder
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength - 1) * 8] : new_target
|
||||
// -- sp[FCA::kArgsLength * 8] : last argument
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength + argc - 1) * 8] : first argument
|
||||
// -- sp[(FCA::kArgsLength + argc) * 8] : receiver
|
||||
// -- sp[(FCA::kArgsLength + argc + 1) * 8] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// Load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
Register scratch2 = callee;
|
||||
__ Ld(accessor_holder,
|
||||
MemOperand(sp, (FCA::kArgsLength + 1 + argc()) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ Ld(scratch, FieldMemOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ Lbu(scratch2, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
||||
__ And(scratch2, scratch2, Operand(1 << Map::kIsConstructor));
|
||||
__ Branch(&skip_looking_for_constructor, ne, scratch2, Operand(zero_reg));
|
||||
__ GetMapConstructor(context, scratch, scratch, scratch2);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ Ld(context, FieldMemOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// Load context from callee.
|
||||
__ Ld(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1694,7 +1667,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
return_value_offset = 2 + FCA::kReturnValueOffset;
|
||||
}
|
||||
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc() + FCA::kArgsLength + 1;
|
||||
// TODO(adamk): Why are we clobbering this immediately?
|
||||
const int32_t stack_space_offset = kInvalidStackOffset;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
|
||||
|
@ -4452,19 +4452,6 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp, Register temp2) {
|
||||
Label done, loop;
|
||||
ld(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done);
|
||||
GetObjectType(result, temp, temp2);
|
||||
Branch(&done, ne, temp2, Operand(MAP_TYPE));
|
||||
ld(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
Branch(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::GetObjectType(Register object,
|
||||
Register map,
|
||||
Register type_reg) {
|
||||
|
@ -1167,11 +1167,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// -------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done, and |temp2| its instance type.
|
||||
void GetMapConstructor(Register result, Register map, Register temp,
|
||||
Register temp2);
|
||||
|
||||
void GetObjectType(Register function,
|
||||
Register map,
|
||||
Register type_reg);
|
||||
|
@ -1592,7 +1592,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- sp[(argc - 1)* 4] : first argument
|
||||
// -- sp[argc * 4] : receiver
|
||||
// -- sp[(argc + 1)* 4] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = r3;
|
||||
@ -1638,33 +1637,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
__ push(holder);
|
||||
|
||||
// Enter a new context
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- sp[0] : holder
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength - 1) * 4] : new_target
|
||||
// -- sp[FCA::kArgsLength * 4] : last argument
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength + argc - 1) * 4] : first argument
|
||||
// -- sp[(FCA::kArgsLength + argc) * 4] : receiver
|
||||
// -- sp[(FCA::kArgsLength + argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// Load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
Register scratch2 = callee;
|
||||
__ LoadP(accessor_holder,
|
||||
MemOperand(sp, (FCA::kArgsLength + 1 + argc()) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ LoadP(scratch, FieldMemOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ lbz(scratch2, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
||||
__ andi(r0, scratch2, Operand(1 << Map::kIsConstructor));
|
||||
__ bne(&skip_looking_for_constructor, cr0);
|
||||
__ GetMapConstructor(context, scratch, scratch, scratch2);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ LoadP(context, FieldMemOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// Load context from callee
|
||||
__ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1713,7 +1686,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
return_value_offset = 2 + FCA::kReturnValueOffset;
|
||||
}
|
||||
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc() + FCA::kArgsLength + 1;
|
||||
MemOperand* stack_space_operand = nullptr;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
|
||||
stack_space_operand, return_value_operand,
|
||||
|
@ -1527,19 +1527,6 @@ void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
|
||||
JumpIfSmi(value, miss);
|
||||
}
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp, Register temp2) {
|
||||
Label done, loop;
|
||||
LoadP(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done);
|
||||
CompareObjectType(result, temp, temp2, MAP_TYPE);
|
||||
bne(&done);
|
||||
LoadP(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
b(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
|
||||
DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs.
|
||||
Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
|
||||
|
@ -862,11 +862,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done, and |temp2| its instance type.
|
||||
void GetMapConstructor(Register result, Register map, Register temp,
|
||||
Register temp2);
|
||||
|
||||
// Compare object type for heap object. heap_object contains a non-Smi
|
||||
// whose object type should be compared with the given type. This both
|
||||
// sets the flags and leaves the object type in the type_reg register.
|
||||
|
@ -1593,7 +1593,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- sp[(argc - 1) * 4] : first argument
|
||||
// -- sp[argc * 4] : receiver
|
||||
// -- sp[(argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = r2;
|
||||
@ -1639,33 +1638,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
__ push(holder);
|
||||
|
||||
// Enter a new context
|
||||
if (is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- sp[0] : holder
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength - 1) * 4] : new_target
|
||||
// -- sp[FCA::kArgsLength * 4] : last argument
|
||||
// -- ...
|
||||
// -- sp[(FCA::kArgsLength + argc - 1) * 4] : first argument
|
||||
// -- sp[(FCA::kArgsLength + argc) * 4] : receiver
|
||||
// -- sp[(FCA::kArgsLength + argc + 1) * 4] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// Load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
Register scratch2 = callee;
|
||||
__ LoadP(accessor_holder,
|
||||
MemOperand(sp, (FCA::kArgsLength + 1 + argc()) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ LoadP(scratch, FieldMemOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ LoadlB(scratch2, FieldMemOperand(scratch, Map::kBitFieldOffset));
|
||||
__ AndP(scratch2, Operand(1 << Map::kIsConstructor));
|
||||
__ bne(&skip_looking_for_constructor, Label::kNear);
|
||||
__ GetMapConstructor(context, scratch, scratch, scratch2);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ LoadP(context, FieldMemOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!is_lazy()) {
|
||||
// Load context from callee
|
||||
__ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1714,7 +1687,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
return_value_offset = 2 + FCA::kReturnValueOffset;
|
||||
}
|
||||
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
|
||||
const int stack_space = argc() + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc() + FCA::kArgsLength + 1;
|
||||
MemOperand* stack_space_operand = nullptr;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
|
||||
stack_space_operand, return_value_operand,
|
||||
|
@ -1459,19 +1459,6 @@ void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
|
||||
JumpIfSmi(value, miss);
|
||||
}
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp, Register temp2) {
|
||||
Label done, loop;
|
||||
LoadP(result, FieldMemOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done);
|
||||
CompareObjectType(result, temp, temp2, MAP_TYPE);
|
||||
bne(&done);
|
||||
LoadP(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
b(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
|
||||
DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs.
|
||||
Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
|
||||
|
@ -1065,11 +1065,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done, and |temp2| its instance type.
|
||||
void GetMapConstructor(Register result, Register map, Register temp,
|
||||
Register temp2);
|
||||
|
||||
// Compare object type for heap object. heap_object contains a non-Smi
|
||||
// whose object type should be compared with the given type. This both
|
||||
// sets the flags and leaves the object type in the type_reg register.
|
||||
|
@ -1483,7 +1483,6 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
// -- ...
|
||||
// -- rsp[argc * 8] : first argument
|
||||
// -- rsp[(argc + 1) * 8] : receiver
|
||||
// -- rsp[(argc + 2) * 8] : accessor_holder
|
||||
// -----------------------------------
|
||||
|
||||
Register callee = rdi;
|
||||
@ -1532,33 +1531,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// enter a new context
|
||||
int argc = this->argc();
|
||||
if (this->is_lazy()) {
|
||||
// ----------- S t a t e -------------------------------------
|
||||
// -- rsp[0] : holder
|
||||
// -- ...
|
||||
// -- rsp[(FCA::kArgsLength - 1) * 8] : new_target
|
||||
// -- rsp[FCA::kArgsLength * 8] : last argument
|
||||
// -- ...
|
||||
// -- rsp[(FCA::kArgsLength + argc - 1) * 8] : first argument
|
||||
// -- rsp[(FCA::kArgsLength + argc) * 8] : receiver
|
||||
// -- rsp[(FCA::kArgsLength + argc + 1) * 8] : accessor_holder
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// load context from accessor_holder
|
||||
Register accessor_holder = context;
|
||||
Register scratch2 = callee;
|
||||
__ movp(accessor_holder,
|
||||
MemOperand(rsp, (argc + FCA::kArgsLength + 1) * kPointerSize));
|
||||
// Look for the constructor if |accessor_holder| is not a function.
|
||||
Label skip_looking_for_constructor;
|
||||
__ movp(scratch, FieldOperand(accessor_holder, HeapObject::kMapOffset));
|
||||
__ testb(FieldOperand(scratch, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsConstructor));
|
||||
__ j(not_zero, &skip_looking_for_constructor, Label::kNear);
|
||||
__ GetMapConstructor(context, scratch, scratch2);
|
||||
__ bind(&skip_looking_for_constructor);
|
||||
__ movp(context, FieldOperand(context, JSFunction::kContextOffset));
|
||||
} else {
|
||||
if (!this->is_lazy()) {
|
||||
// load context from callee
|
||||
__ movp(context, FieldOperand(callee, JSFunction::kContextOffset));
|
||||
}
|
||||
@ -1606,7 +1579,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
|
||||
FCA::kArgsLength - FCA::kContextSaveIndex);
|
||||
Operand return_value_operand = args_from_rbp.GetArgumentOperand(
|
||||
this->is_store() ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset);
|
||||
const int stack_space = argc + FCA::kArgsLength + 2;
|
||||
const int stack_space = argc + FCA::kArgsLength + 1;
|
||||
Operand* stack_space_operand = nullptr;
|
||||
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, callback_arg,
|
||||
stack_space, stack_space_operand,
|
||||
|
@ -2180,19 +2180,6 @@ void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::GetMapConstructor(Register result, Register map,
|
||||
Register temp) {
|
||||
Label done, loop;
|
||||
movp(result, FieldOperand(map, Map::kConstructorOrBackPointerOffset));
|
||||
bind(&loop);
|
||||
JumpIfSmi(result, &done, Label::kNear);
|
||||
CmpObjectType(result, MAP_TYPE, temp);
|
||||
j(not_equal, &done, Label::kNear);
|
||||
movp(result, FieldOperand(result, Map::kConstructorOrBackPointerOffset));
|
||||
jmp(&loop);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
|
||||
DCHECK_GT(value, 0);
|
||||
if (FLAG_native_code_counters && counter->Enabled()) {
|
||||
|
@ -910,10 +910,6 @@ class MacroAssembler : public TurboAssembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Support functions.
|
||||
|
||||
// Machine code version of Map::GetConstructor().
|
||||
// |temp| holds |result|'s map when done.
|
||||
void GetMapConstructor(Register result, Register map, Register temp);
|
||||
|
||||
// Load the global proxy from the current context.
|
||||
void LoadGlobalProxy(Register dst) {
|
||||
LoadNativeContextSlot(Context::GLOBAL_PROXY_INDEX, dst);
|
||||
|
@ -37,10 +37,7 @@ TEST_F(ObjectTest, SetAccessorWhenUnconfigurablePropAlreadyDefined) {
|
||||
|
||||
using LapContextTest = TestWithIsolate;
|
||||
|
||||
// TODO(yukishiino): Enable this unittest once
|
||||
// PropertyAccessInfo::accessor_holder() gets supported. Currently we're using
|
||||
// PropertyAccessInfo::holder(), which doesn't return the accessor holder.
|
||||
TEST_F(LapContextTest, DISABLED_CurrentContextInLazyAccessorOnPrototype) {
|
||||
TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) {
|
||||
// The receiver object is created in |receiver_context|, but its prototype
|
||||
// object is created in |prototype_context|, and the property is accessed
|
||||
// from |caller_context|.
|
||||
|
Loading…
Reference in New Issue
Block a user