Commit 50e1019d authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[ic] Support data-driven accessor pairs

The ForDeopt stub isn't actually necessary anymore; but I don't want to fix the deoptimizer in the same CL.

BUG=v8:5561

Change-Id: I7101cec4b783949bcfbf1ebdb80541d1b558e2e2
Reviewed-on: https://chromium-review.googlesource.com/455858
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43896}
parent ab4233e3
......@@ -2971,6 +2971,10 @@ Node* CodeStubAssembler::IsPropertyCell(Node* object) {
return IsPropertyCellMap(LoadMap(object));
}
Node* CodeStubAssembler::IsAccessorPair(Node* object) {
return IsAccessorPairMap(LoadMap(object));
}
Node* CodeStubAssembler::IsHeapNumber(Node* object) {
return IsHeapNumberMap(LoadMap(object));
}
......@@ -5061,7 +5065,7 @@ Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
GotoIf(Word32Equal(LoadInstanceType(accessor_pair),
Int32Constant(ACCESSOR_INFO_TYPE)),
if_bailout);
CSA_ASSERT(this, HasInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE));
CSA_ASSERT(this, IsAccessorPair(accessor_pair));
Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
Node* getter_map = LoadMap(getter);
Node* instance_type = LoadMapInstanceType(getter_map);
......
......@@ -23,6 +23,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
#define HEAP_CONSTANT_LIST(V) \
V(AccessorInfoMap, AccessorInfoMap) \
V(AccessorPairMap, AccessorPairMap) \
V(AllocationSiteMap, AllocationSiteMap) \
V(BooleanMap, BooleanMap) \
V(CodeMap, CodeMap) \
......@@ -707,6 +708,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsCallable(Node* object);
Node* IsBoolean(Node* object);
Node* IsPropertyCell(Node* object);
Node* IsAccessorPair(Node* object);
Node* IsHeapNumber(Node* object);
Node* IsName(Node* object);
Node* IsSymbol(Node* object);
......
......@@ -297,7 +297,7 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
}
Label constant(this), field(this), normal(this, Label::kDeferred),
interceptor(this, Label::kDeferred), nonexistent(this),
interceptor(this, Label::kDeferred), nonexistent(this), accessor(this),
global(this, Label::kDeferred);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field);
......@@ -310,6 +310,9 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNormal)),
&normal);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kAccessor)),
&accessor);
Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kGlobal)), &global,
&interceptor);
......@@ -373,6 +376,29 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
}
}
Bind(&accessor);
{
Comment("accessor_load");
Node* descriptors = LoadMapDescriptors(LoadMap(holder));
Node* descriptor = DecodeWord<LoadHandler::DescriptorBits>(handler_word);
Node* scaled_descriptor =
IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
Node* value_index =
IntPtrAdd(scaled_descriptor,
IntPtrConstant(DescriptorArray::kFirstIndex +
DescriptorArray::kEntryValueIndex));
CSA_ASSERT(this,
UintPtrLessThan(descriptor,
LoadAndUntagFixedArrayBaseLength(descriptors)));
Node* accessor_pair = LoadFixedArrayElement(descriptors, value_index);
CSA_ASSERT(this, IsAccessorPair(accessor_pair));
Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(getter)));
Callable callable = CodeFactory::Call(isolate());
exit_point->Return(CallJS(callable, p->context, getter, p->receiver));
}
Bind(&global);
{
CSA_ASSERT(this, IsPropertyCell(holder));
......
......@@ -18,33 +18,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
// ----------- S t a t e -------------
// -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
if (accessor_index >= 0) {
__ push(receiver);
__ LoadAccessor(r1, holder, accessor_index, ACCESSOR_GETTER);
__ mov(r0, Operand(0));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(cp);
}
......
......@@ -237,28 +237,13 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
__ Ret();
}
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ Push(cp);
if (accessor_index >= 0) {
__ Push(receiver);
__ LoadAccessor(x1, holder, accessor_index, ACCESSOR_GETTER);
__ Mov(x0, 0);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ Pop(cp);
}
......
......@@ -122,14 +122,6 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
return GetCode(kind(), name);
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
Handle<Name> name, int accessor_index, int expected_arguments) {
Register holder = Frontend(name);
GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index,
expected_arguments);
return GetCode(kind(), name);
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
Handle<JSObject> object, Handle<Name> name, int accessor_index,
int expected_arguments) {
......
......@@ -123,16 +123,7 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
const CallOptimization& call_optimization,
int accessor_index, Handle<Code> slow_stub);
Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
int expected_arguments);
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
Register receiver, Register holder,
int accessor_index, int expected_arguments);
static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1);
}
static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm);
protected:
virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
......
......@@ -42,6 +42,12 @@ Handle<Smi> LoadHandler::LoadConstant(Isolate* isolate, int descriptor) {
return handle(Smi::FromInt(config), isolate);
}
Handle<Smi> LoadHandler::LoadAccessor(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kAccessor) | IsAccessorInfoBits::encode(false) |
DescriptorBits::encode(descriptor);
return handle(Smi::FromInt(config), isolate);
}
Handle<Smi> LoadHandler::LoadApiGetter(Isolate* isolate, int descriptor) {
int config = KindBits::encode(kConstant) | IsAccessorInfoBits::encode(true) |
DescriptorBits::encode(descriptor);
......
......@@ -22,6 +22,7 @@ class LoadHandler {
kGlobal,
kField,
kConstant,
kAccessor,
kInterceptor,
kNonExistent
};
......@@ -105,6 +106,9 @@ class LoadHandler {
// Creates a Smi-handler for loading a constant from fast object.
static inline Handle<Smi> LoadConstant(Isolate* isolate, int descriptor);
// Creates a Smi-handler for calling a getter on a fast object.
static inline Handle<Smi> LoadAccessor(Isolate* isolate, int descriptor);
// Creates a Smi-handler for loading an Api getter property from fast object.
static inline Handle<Smi> LoadApiGetter(Isolate* isolate, int descriptor);
......
......@@ -17,27 +17,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(esi);
if (accessor_index >= 0) {
__ push(receiver);
__ LoadAccessor(edi, holder, accessor_index, ACCESSOR_GETTER);
__ Set(eax, 0);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(esi);
......
......@@ -1330,14 +1330,32 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
return slow_stub();
}
Handle<Smi> smi_handler;
if (holder->HasFastProperties()) {
CallOptimization call_optimization(getter);
if (call_optimization.is_simple_api_call() &&
!call_optimization.IsCompatibleReceiverMap(map, holder)) {
if (call_optimization.is_simple_api_call()) {
if (!call_optimization.IsCompatibleReceiverMap(map, holder)) {
return slow_stub();
}
break;
}
smi_handler =
LoadHandler::LoadAccessor(isolate(), lookup->GetAccessorIndex());
if (receiver_is_holder) return smi_handler;
} else if (receiver_is_holder && !holder->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
return LoadHandler::LoadNormal(isolate());
} else if (holder->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
smi_handler = LoadHandler::LoadGlobal(isolate());
} else {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
smi_handler = LoadHandler::LoadNormal(isolate());
}
return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
}
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
......@@ -1441,20 +1459,13 @@ Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
isolate());
CallOptimization call_optimization(getter);
NamedLoadHandlerCompiler compiler(isolate(), map, holder);
if (call_optimization.is_simple_api_call()) {
DCHECK(call_optimization.is_simple_api_call());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
int index = lookup->GetAccessorIndex();
Handle<Code> code = compiler.CompileLoadCallback(
lookup->name(), call_optimization, index, slow_stub());
return code;
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
int expected_arguments = Handle<JSFunction>::cast(getter)
->shared()
->internal_formal_parameter_count();
return compiler.CompileLoadViaGetter(
lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
}
case LookupIterator::INTERCEPTOR:
case LookupIterator::DATA:
......
......@@ -17,33 +17,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
// ----------- S t a t e -------------
// -- a0 : receiver
// -- a2 : name
// -- ra : return address
// -----------------------------------
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
if (accessor_index >= 0) {
__ push(receiver);
__ LoadAccessor(a1, holder, accessor_index, ACCESSOR_GETTER);
__ li(a0, Operand(0));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(cp);
}
......
......@@ -17,33 +17,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
// ----------- S t a t e -------------
// -- a0 : receiver
// -- a2 : name
// -- ra : return address
// -----------------------------------
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
if (accessor_index >= 0) {
__ push(receiver);
__ LoadAccessor(a1, holder, accessor_index, ACCESSOR_GETTER);
__ li(a0, Operand(V8_INT64_C(0)));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(cp);
}
......
......@@ -17,33 +17,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
// ----------- S t a t e -------------
// -- r3 : receiver
// -- r5 : name
// -- lr : return address
// -----------------------------------
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
if (accessor_index >= 0) {
__ push(receiver);
__ LoadAccessor(r4, holder, accessor_index, ACCESSOR_GETTER);
__ li(r3, Operand::Zero());
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(cp);
}
......
......@@ -17,33 +17,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
// ----------- S t a t e -------------
// -- r2 : receiver
// -- r4 : name
// -- lr : return address
// -----------------------------------
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
if (accessor_index >= 0) {
__ Push(receiver);
__ LoadAccessor(r3, holder, accessor_index, ACCESSOR_GETTER);
__ LoadImmP(r2, Operand::Zero());
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(cp);
}
......
......@@ -232,33 +232,12 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
__ ret(0);
}
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
// ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ pushq(rsi);
if (accessor_index >= 0) {
__ Push(receiver);
__ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_GETTER);
__ Set(rax, 0);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
// Remember the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ popq(rsi);
}
......
......@@ -17,28 +17,13 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments) {
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(esi);
if (accessor_index >= 0) {
__ push(receiver);
__ LoadAccessor(edi, holder, accessor_index, ACCESSOR_GETTER);
__ Set(eax, 0);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
}
// Restore context register.
__ pop(esi);
}
......
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