Commit c82cd313 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

Drop custom accessor deoptimization support

Previously StaNamedProperty and StaKeyedProperty were in a weird state where
they claimed to not touch the accumulator, but actually did in case they were
deopted in the middle. A frame was added in the middle to overwrite the 
accumulator again with the right value before returning from the setter, using
a lot of complexity in the deoptimizer.

This changes those instructions to be marked as writing to the accumulator
(e.g., the result of the setter), and uses to manually store and reload into
the accumulator the value being stored.

If we want to avoid the additional bytecodes, we could make sure that bytecodes
that claim to leave the accumulator alone don't deopt back to Advance/Dispatch
but LoadAccumulatorWithValue/Advance/Dispatch. That's in a way similar to what
happened before this CL, but I believe could be implemented much simpler.


Bug: 
Change-Id: I4850a690ef5a30976701d0e050951faa46fd1c18
Reviewed-on: https://chromium-review.googlesource.com/753487Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49159}
parent 5b0a753d
......@@ -211,14 +211,12 @@ namespace internal {
TFH(LoadGlobalIC_Slow, LoadGlobalWithVector) \
TFH(LoadField, LoadField) \
TFH(LoadIC_FunctionPrototype, LoadWithVector) \
ASM(LoadIC_Getter_ForDeopt) \
TFH(LoadIC_Miss, LoadWithVector) \
TFH(LoadIC_Slow, LoadWithVector) \
TFH(LoadIC_StringLength, LoadWithVector) \
TFH(LoadIC_Uninitialized, LoadWithVector) \
TFH(StoreGlobalIC_Slow, StoreWithVector) \
TFH(StoreIC_Miss, StoreWithVector) \
ASM(StoreIC_Setter_ForDeopt) \
TFH(StoreIC_Uninitialized, StoreWithVector) \
\
/* Promise helpers */ \
......
......@@ -93,10 +93,6 @@ TF_BUILTIN(LoadGlobalIC_Slow, CodeStubAssembler) {
TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, name, slot, vector);
}
void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
}
TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
Node* name = Parameter(Descriptor::kName);
......@@ -141,10 +137,6 @@ TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) {
receiver, name);
}
void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
TF_BUILTIN(StoreGlobalIC_Slow, CodeStubAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
Node* name = Parameter(Descriptor::kName);
......
......@@ -876,12 +876,6 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor(
bailout_id, shared_info_id, parameter_count);
break;
}
case FrameStateType::kGetterStub:
translation->BeginGetterStubFrame(shared_info_id);
break;
case FrameStateType::kSetterStub:
translation->BeginSetterStubFrame(shared_info_id);
break;
}
TranslateFrameStateDescriptorOperands(descriptor, iter, state_combine,
......
......@@ -63,12 +63,6 @@ std::ostream& operator<<(std::ostream& os, FrameStateType type) {
case FrameStateType::kJavaScriptBuiltinContinuation:
os << "JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME";
break;
case FrameStateType::kGetterStub:
os << "GETTER_STUB";
break;
case FrameStateType::kSetterStub:
os << "SETTER_STUB";
break;
}
return os;
}
......
......@@ -63,8 +63,6 @@ enum class FrameStateType {
kInterpretedFunction, // Represents an InterpretedFrame.
kArgumentsAdaptor, // Represents an ArgumentsAdaptorFrame.
kConstructStub, // Represents a ConstructStubFrame.
kGetterStub, // Represents a GetterStubFrame.
kSetterStub, // Represents a SetterStubFrame.
kBuiltinContinuation, // Represents a continuation to a stub.
kJavaScriptBuiltinContinuation // Represents a continuation to a JavaScipt
// builtin.
......
......@@ -1583,26 +1583,13 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
Handle<SharedFunctionInfo> shared_info =
frame_info.shared_info().ToHandleChecked();
// We need a FrameState for the getter stub to restore the correct
// context before returning to fullcodegen.
FrameStateFunctionInfo const* frame_info0 =
common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub, 1, 0,
shared_info);
Node* frame_state0 = graph()->NewNode(
common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
frame_info0),
graph()->NewNode(common()->StateValues(1, SparseInputMask::Dense()),
receiver),
jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(), context,
target, frame_state);
// Introduce the call to the getter function.
Node* value;
if (access_info.constant()->IsJSFunction()) {
value = *effect = *control = graph()->NewNode(
jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
ConvertReceiverMode::kNotNullOrUndefined),
target, receiver, context, frame_state0, *effect, *control);
target, receiver, context, frame_state, *effect, *control);
} else {
DCHECK(access_info.constant()->IsFunctionTemplateInfo());
Handle<FunctionTemplateInfo> function_template_info(
......@@ -1612,7 +1599,7 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
access_info.holder().is_null()
? receiver
: jsgraph()->Constant(access_info.holder().ToHandleChecked());
value = InlineApiCall(receiver, holder, frame_state0, nullptr, effect,
value = InlineApiCall(receiver, holder, frame_state, nullptr, effect,
control, shared_info, function_template_info);
}
// Remember to rewire the IfException edge if this is inside a try-block.
......@@ -1635,25 +1622,12 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
Handle<SharedFunctionInfo> shared_info =
frame_info.shared_info().ToHandleChecked();
// We need a FrameState for the setter stub to restore the correct
// context and return the appropriate value to fullcodegen.
FrameStateFunctionInfo const* frame_info0 =
common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub, 2, 0,
shared_info);
Node* frame_state0 = graph()->NewNode(
common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
frame_info0),
graph()->NewNode(common()->StateValues(2, SparseInputMask::Dense()),
receiver, value),
jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(), context,
target, frame_state);
// Introduce the call to the setter function.
if (access_info.constant()->IsJSFunction()) {
*effect = *control = graph()->NewNode(
jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
ConvertReceiverMode::kNotNullOrUndefined),
target, receiver, value, context, frame_state0, *effect, *control);
target, receiver, value, context, frame_state, *effect, *control);
} else {
DCHECK(access_info.constant()->IsFunctionTemplateInfo());
Handle<FunctionTemplateInfo> function_template_info(
......@@ -1663,7 +1637,7 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
access_info.holder().is_null()
? receiver
: jsgraph()->Constant(access_info.holder().ToHandleChecked());
InlineApiCall(receiver, holder, frame_state0, value, effect, control,
InlineApiCall(receiver, holder, frame_state, value, effect, control,
shared_info, function_template_info);
}
// Remember to rewire the IfException edge if this is inside a try-block.
......
This diff is collapsed.
......@@ -121,8 +121,6 @@ class TranslatedFrame {
public:
enum Kind {
kInterpretedFunction,
kGetter,
kSetter,
kArgumentsAdaptor,
kConstructStub,
kBuiltinContinuation,
......@@ -487,8 +485,6 @@ class Deoptimizer : public Malloced {
int frame_index);
void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
int frame_index);
void DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
int frame_index, bool is_setter_stub_frame);
void DoComputeBuiltinContinuation(TranslatedFrame* translated_frame,
int frame_index, bool java_script_frame);
......@@ -827,8 +823,6 @@ class TranslationIterator BASE_EMBEDDED {
V(BUILTIN_CONTINUATION_FRAME) \
V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME) \
V(CONSTRUCT_STUB_FRAME) \
V(GETTER_STUB_FRAME) \
V(SETTER_STUB_FRAME) \
V(ARGUMENTS_ADAPTOR_FRAME) \
V(DUPLICATED_OBJECT) \
V(ARGUMENTS_ELEMENTS) \
......@@ -879,8 +873,6 @@ class Translation BASE_EMBEDDED {
unsigned height);
void BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
int literal_id, unsigned height);
void BeginGetterStubFrame(int literal_id);
void BeginSetterStubFrame(int literal_id);
void ArgumentsElements(CreateArgumentsType type);
void ArgumentsLength(CreateArgumentsType type);
void BeginCapturedObject(int length);
......
......@@ -82,16 +82,6 @@ void Heap::SetConstructStubInvokeDeoptPCOffset(int pc_offset) {
set_construct_stub_invoke_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetGetterStubDeoptPCOffset(int pc_offset) {
DCHECK_EQ(Smi::kZero, getter_stub_deopt_pc_offset());
set_getter_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetSetterStubDeoptPCOffset(int pc_offset) {
DCHECK_EQ(Smi::kZero, setter_stub_deopt_pc_offset());
set_setter_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetInterpreterEntryReturnPCOffset(int pc_offset) {
DCHECK_EQ(Smi::kZero, interpreter_entry_return_pc_offset());
set_interpreter_entry_return_pc_offset(Smi::FromInt(pc_offset));
......
......@@ -256,8 +256,6 @@ using v8::MemoryPressureLevel;
ConstructStubCreateDeoptPCOffset) \
V(Smi, construct_stub_invoke_deopt_pc_offset, \
ConstructStubInvokeDeoptPCOffset) \
V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset) \
V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset) \
V(Smi, interpreter_entry_return_pc_offset, InterpreterEntryReturnPCOffset)
#define ROOT_LIST(V) \
......@@ -839,8 +837,6 @@ class Heap {
void SetArgumentsAdaptorDeoptPCOffset(int pc_offset);
void SetConstructStubCreateDeoptPCOffset(int pc_offset);
void SetConstructStubInvokeDeoptPCOffset(int pc_offset);
void SetGetterStubDeoptPCOffset(int pc_offset);
void SetSetterStubDeoptPCOffset(int pc_offset);
void SetInterpreterEntryReturnPCOffset(int pc_offset);
void SetSerializedTemplates(FixedArray* templates);
......
......@@ -18,20 +18,6 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// 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);
}
__ Ret();
}
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
......@@ -41,39 +27,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(cp);
// Save value register, so we can restore it later.
__ push(value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver, value());
__ LoadAccessor(r1, holder, accessor_index, ACCESSOR_SETTER);
__ mov(r0, Operand(1));
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
__ pop(r0);
// Restore context register.
__ pop(cp);
__ Push(receiver, value());
__ LoadAccessor(r1, holder, accessor_index, ACCESSOR_SETTER);
__ mov(r0, Operand(1));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ Ret();
}
......
......@@ -190,48 +190,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context and value registers, so we can restore them later.
__ Push(cp, value());
if (accessor_index >= 0) {
DCHECK(!AreAliased(holder, scratch));
DCHECK(!AreAliased(receiver, scratch));
DCHECK(!AreAliased(value(), scratch));
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ Ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver, value());
__ LoadAccessor(x1, holder, accessor_index, ACCESSOR_SETTER);
__ Mov(x0, 1);
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(!AreAliased(holder, scratch));
DCHECK(!AreAliased(receiver, scratch));
DCHECK(!AreAliased(value(), scratch));
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ Ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
// Also, restore the context register.
__ Pop(x0, cp);
}
__ Ret();
}
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// 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);
__ Push(receiver, value());
__ LoadAccessor(x1, holder, accessor_index, ACCESSOR_SETTER);
__ Mov(x0, 1);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ Ret();
}
......
......@@ -110,12 +110,6 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
};
class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
public:
static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm);
};
class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
public:
// All store handlers use StoreWithVectorDescriptor calling convention.
......@@ -151,11 +145,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
int accessor_index, int expected_arguments,
Register scratch);
static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
no_reg);
}
protected:
virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Label* miss);
......
......@@ -17,21 +17,6 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// 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);
}
__ ret(0);
}
void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
Register slot) {
MacroAssembler* masm = this->masm();
......@@ -211,47 +196,24 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ push(esi);
// Save value register, so we can restore it later.
__ push(value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
__ mov(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ push(receiver);
__ push(value());
__ LoadAccessor(edi, holder, accessor_index, ACCESSOR_SETTER);
__ Set(eax, 1);
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
__ mov(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
__ pop(eax);
// Restore context register.
__ pop(esi);
}
if (accessor_index >= 0) {
__ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
} else {
// If we generate a global code snippet for deoptimization only, don't try
// to drop stack arguments for the StoreIC because they are not a part of
// expression stack and deoptimizer does not reconstruct them.
__ ret(0);
__ push(receiver);
__ push(value());
__ LoadAccessor(edi, holder, accessor_index, ACCESSOR_SETTER);
__ Set(eax, 1);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize);
}
#undef __
......
......@@ -17,20 +17,6 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// 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);
}
__ Ret();
}
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
......@@ -40,35 +26,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context and value registers, so we can restore them later.
__ Push(cp, value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ lw(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver, value());
__ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER);
__ li(a0, Operand(1));
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ lw(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
// Restore context register.
__ Pop(cp, v0);
__ Push(receiver, value());
__ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER);
__ li(a0, Operand(1));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ Ret();
}
......
......@@ -17,20 +17,6 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// 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);
}
__ Ret();
}
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
......@@ -40,35 +26,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context and value registers, so we can restore them later.
__ Push(cp, value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ Ld(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver, value());
__ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER);
__ li(a0, Operand(1));
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ Ld(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
// Restore context register.
__ Pop(cp, v0);
__ Push(receiver, value());
__ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER);
__ li(a0, Operand(1));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ Ret();
}
......
......@@ -17,20 +17,6 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// 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);
}
__ Ret();
}
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
......@@ -40,36 +26,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
// Save context register
// Save value register, so we can restore it later.
__ Push(cp, value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ LoadP(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver, value());
__ LoadAccessor(r4, holder, accessor_index, ACCESSOR_SETTER);
__ li(r3, Operand(1));
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ LoadP(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
// Restore context register.
__ Pop(cp, r3);
__ Push(receiver, value());
__ LoadAccessor(r4, holder, accessor_index, ACCESSOR_SETTER);
__ li(r3, Operand(1));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ Ret();
}
......
......@@ -17,19 +17,6 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// 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);
}
__ Ret();
}
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
......@@ -39,36 +26,22 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
// Save value register, so we can restore it later.
__ Push(cp, value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ LoadP(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver, value());
__ LoadAccessor(r3, holder, accessor_index, ACCESSOR_SETTER);
__ LoadImmP(r2, Operand(1));
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ LoadP(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
// Restore context register.
__ Pop(cp, r2);
__ Push(receiver, value());
__ LoadAccessor(r3, holder, accessor_index, ACCESSOR_SETTER);
__ LoadImmP(r2, Operand(1));
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ Ret();
}
......
......@@ -186,52 +186,23 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Save context register
__ pushq(rsi);
// Save value register, so we can restore it later.
__ Push(value());
if (accessor_index >= 0) {
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ movp(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
__ Push(receiver);
__ Push(value());
__ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_SETTER);
__ Set(rax, 1);
__ 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()->SetSetterStubDeoptPCOffset(masm->pc_offset());
DCHECK(holder != scratch);
DCHECK(receiver != scratch);
DCHECK(value() != scratch);
// Call the JavaScript setter with receiver and value on the stack.
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ movp(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
}
// We have to return the passed value, not the return value of the setter.
__ Pop(rax);
// Restore context register.
__ popq(rsi);
}
__ ret(0);
}
void NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(
MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Remember the place to continue after deoptimization.
masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
// Restore context register.
__ popq(rsi);
__ Push(receiver);
__ Push(value());
__ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_SETTER);
__ Set(rax, 1);
__ Call(masm->isolate()->builtins()->CallFunction(
ConvertReceiverMode::kNotNullOrUndefined),
RelocInfo::CODE_TARGET);
}
__ ret(0);
}
......
......@@ -1520,6 +1520,7 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr) {
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
builder()->StoreNamedProperty(object, name, feedback_index(slot),
language_mode());
builder()->LoadAccumulatorWithRegister(value);
break;
}
case KEYED_PROPERTY: {
......@@ -1532,6 +1533,7 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr) {
FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
builder()->StoreKeyedProperty(object, key, feedback_index(slot),
language_mode());
builder()->LoadAccumulatorWithRegister(value);
break;
}
case NAMED_SUPER_PROPERTY: {
......@@ -2706,14 +2708,30 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
}
case NAMED_PROPERTY: {
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
Register value;
if (!execution_result()->IsEffect()) {
value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(value);
}
builder()->StoreNamedProperty(object, name, feedback_index(slot),
language_mode());
if (!execution_result()->IsEffect()) {
builder()->LoadAccumulatorWithRegister(value);
}
break;
}
case KEYED_PROPERTY: {
FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
Register value;
if (!execution_result()->IsEffect()) {
value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(value);
}
builder()->StoreKeyedProperty(object, key, feedback_index(slot),
language_mode());
if (!execution_result()->IsEffect()) {
builder()->LoadAccumulatorWithRegister(value);
}
break;
}
case NAMED_SUPER_PROPERTY: {
......@@ -3745,14 +3763,30 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
}
case NAMED_PROPERTY: {
FeedbackSlot slot = feedback_spec()->AddStoreICSlot(language_mode());
Register value;
if (!execution_result()->IsEffect()) {
value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(value);
}
builder()->StoreNamedProperty(object, name, feedback_index(slot),
language_mode());
if (!execution_result()->IsEffect()) {
builder()->LoadAccumulatorWithRegister(value);
}
break;
}
case KEYED_PROPERTY: {
FeedbackSlot slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
Register value;
if (!execution_result()->IsEffect()) {
value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(value);
}
builder()->StoreKeyedProperty(object, key, feedback_index(slot),
language_mode());
if (!execution_result()->IsEffect()) {
builder()->LoadAccumulatorWithRegister(value);
}
break;
}
case NAMED_SUPER_PROPERTY: {
......
......@@ -93,11 +93,11 @@ namespace interpreter {
OperandType::kUImm) \
\
/* Propery stores (StoreIC) operations */ \
V(StaNamedProperty, AccumulatorUse::kRead, OperandType::kReg, \
V(StaNamedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
V(StaNamedOwnProperty, AccumulatorUse::kRead, OperandType::kReg, \
V(StaNamedOwnProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
V(StaKeyedProperty, AccumulatorUse::kRead, OperandType::kReg, \
V(StaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kReg, OperandType::kIdx) \
V(StaDataPropertyInLiteral, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kReg, OperandType::kFlag8, OperandType::kIdx) \
......
......@@ -631,8 +631,12 @@ class InterpreterStoreNamedPropertyAssembler : public InterpreterAssembler {
Node* smi_slot = SmiTag(raw_slot);
Node* feedback_vector = LoadFeedbackVector();
Node* context = GetContext();
CallStub(ic.descriptor(), code_target, context, object, name, value,
smi_slot, feedback_vector);
Node* result = CallStub(ic.descriptor(), code_target, context, object, name,
value, smi_slot, feedback_vector);
// It doesn't really matter what we write to the accumulator here, since we
// restore to the correct value on the outside. Storing the result means we
// don't need to keep unnecessary state alive across the callstub.
SetAccumulator(result);
Dispatch();
}
};
......@@ -673,8 +677,12 @@ IGNITION_HANDLER(StaKeyedProperty, InterpreterAssembler) {
Node* smi_slot = SmiTag(raw_slot);
Node* feedback_vector = LoadFeedbackVector();
Node* context = GetContext();
CallStub(ic.descriptor(), code_target, context, object, name, value, smi_slot,
feedback_vector);
Node* result = CallStub(ic.descriptor(), code_target, context, object, name,
value, smi_slot, feedback_vector);
// It doesn't really matter what we write to the accumulator here, since we
// restore to the correct value on the outside. Storing the result means we
// don't need to keep unnecessary state alive across the callstub.
SetAccumulator(result);
Dispatch();
}
......
......@@ -14223,15 +14223,6 @@ void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) { // NOLINT
break;
}
case Translation::GETTER_STUB_FRAME:
case Translation::SETTER_STUB_FRAME: {
int shared_info_id = iterator.Next();
Object* shared_info = LiteralArray()->get(shared_info_id);
os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
->DebugName()) << "}";
break;
}
case Translation::REGISTER: {
int reg_code = iterator.Next();
os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
......
......@@ -95,9 +95,9 @@ handlers: [
snippet: "
var a = { val: 1 }; return a.val++;
"
frame size: 3
frame size: 4
parameter count: 1
bytecode array length: 26
bytecode array length: 28
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
......@@ -106,6 +106,7 @@ bytecodes: [
B(ToNumeric), U8(3),
B(Star), R(2),
B(Inc), U8(3),
B(Star), R(3),
/* 66 E> */ B(StaNamedProperty), R(1), U8(1), U8(4),
B(Ldar), R(2),
/* 69 S> */ B(Return),
......@@ -121,16 +122,18 @@ handlers: [
snippet: "
var a = { val: 1 }; return --a.val;
"
frame size: 2
frame size: 3
parameter count: 1
bytecode array length: 20
bytecode array length: 24
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Mov), R(1), R(0),
/* 54 S> */ B(LdaNamedProperty), R(1), U8(1), U8(1),
B(Dec), U8(3),
B(Star), R(2),
/* 65 E> */ B(StaNamedProperty), R(1), U8(1), U8(4),
B(Ldar), R(2),
/* 69 S> */ B(Return),
]
constant pool: [
......@@ -144,9 +147,9 @@ handlers: [
snippet: "
var name = 'var'; var a = { val: 1 }; return a[name]--;
"
frame size: 5
frame size: 6
parameter count: 1
bytecode array length: 31
bytecode array length: 33
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(LdaConstant), U8(0),
......@@ -158,6 +161,7 @@ bytecodes: [
B(ToNumeric), U8(3),
B(Star), R(4),
B(Dec), U8(3),
B(Star), R(5),
/* 86 E> */ B(StaKeyedProperty), R(2), R(0), U8(4),
B(Ldar), R(4),
/* 89 S> */ B(Return),
......@@ -173,9 +177,9 @@ handlers: [
snippet: "
var name = 'var'; var a = { val: 1 }; return ++a[name];
"
frame size: 3
frame size: 5
parameter count: 1
bytecode array length: 25
bytecode array length: 29
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(LdaConstant), U8(0),
......@@ -185,7 +189,9 @@ bytecodes: [
/* 72 S> */ B(Ldar), R(0),
/* 83 E> */ B(LdaKeyedProperty), R(2), U8(1),
B(Inc), U8(3),
B(Star), R(4),
/* 87 E> */ B(StaKeyedProperty), R(2), R(0), U8(4),
B(Ldar), R(4),
/* 89 S> */ B(Return),
]
constant pool: [
......@@ -254,9 +260,9 @@ handlers: [
snippet: "
var idx = 1; var a = [1, 2]; return a[idx++] = 2;
"
frame size: 4
frame size: 5
parameter count: 1
bytecode array length: 28
bytecode array length: 32
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 44 S> */ B(LdaSmi), I8(1),
......@@ -269,7 +275,9 @@ bytecodes: [
B(Inc), U8(1),
B(Star), R(0),
B(LdaSmi), I8(2),
B(Star), R(4),
/* 79 E> */ B(StaKeyedProperty), R(1), R(3), U8(2),
B(Ldar), R(4),
/* 83 S> */ B(Return),
]
constant pool: [
......
......@@ -306,13 +306,14 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 26
bytecode array length: 28
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
B(Star), R(0),
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(41), R(1),
/* 64 E> */ B(StaNamedOwnProperty), R(1), U8(2), U8(1),
B(Ldar), R(0),
/* 68 E> */ B(ToName), R(2),
B(LdaSmi), I8(1),
B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(3),
......
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