Commit eccf1867 authored by Creddy's avatar Creddy Committed by Commit Bot

[interpreter] Separate bytecodes for one-shot property loads and stores

Create LdaNamedPropertyNoFeedback and StaNamedPropertyNoFeedback
for one-shot property loads and stores. This CL replaces the runtime
calls with new bytecodes for named property load stores in one-shot code.
the runtime calls needed extra set of consecutive registers and
additional move instructions. This increased the size of
bytecode-array and possibly extended the life time of objects.
By replacing them with NoFeedback bytecodes we avoid these issues.

Bug: v8:8072
Change-Id: I20a38a5ce9940026171d870d354787fe0b7c5a6f
Reviewed-on: https://chromium-review.googlesource.com/1196725Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Chandan Reddy <chandanreddy@google.com>
Cr-Commit-Position: refs/heads/master@{#56211}
parent 7f7545cf
......@@ -1339,6 +1339,17 @@ void BytecodeGraphBuilder::VisitLdaNamedProperty() {
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitLdaNamedPropertyNoFeedback() {
PrepareEagerCheckpoint();
Node* object =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Handle<Name> name(
Name::cast(bytecode_iterator().GetConstantForIndexOperand(1)), isolate());
const Operator* op = javascript()->LoadNamed(name, VectorSlotPair());
Node* node = NewNode(op, object);
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
PrepareEagerCheckpoint();
Node* key = environment()->LookupAccumulator();
......@@ -1402,6 +1413,21 @@ void BytecodeGraphBuilder::VisitStaNamedProperty() {
BuildNamedStore(StoreMode::kNormal);
}
void BytecodeGraphBuilder::VisitStaNamedPropertyNoFeedback() {
PrepareEagerCheckpoint();
Node* value = environment()->LookupAccumulator();
Node* object =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Handle<Name> name(
Name::cast(bytecode_iterator().GetConstantForIndexOperand(1)), isolate());
LanguageMode language_mode =
static_cast<LanguageMode>(bytecode_iterator().GetFlagOperand(2));
const Operator* op =
javascript()->StoreNamed(language_mode, name, VectorSlotPair());
Node* node = NewNode(op, object, value);
environment()->RecordAfterState(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitStaNamedOwnProperty() {
BuildNamedStore(StoreMode::kOwn);
}
......
......@@ -169,6 +169,12 @@ void JSGenericLowering::LowerJSLoadNamed(Node* node) {
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
if (!p.feedback().IsValid()) {
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kGetProperty);
ReplaceWithStubCall(node, callable, flags);
return;
}
node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
Callable callable = Builtins::CallableFor(
......@@ -231,6 +237,12 @@ void JSGenericLowering::LowerJSStoreNamed(Node* node) {
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
if (!p.feedback().IsValid()) {
node->InsertInput(
zone(), 3, jsgraph()->SmiConstant(static_cast<int>(p.language_mode())));
ReplaceWithRuntimeCall(node, Runtime::kSetNamedProperty);
return;
}
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
Callable callable =
......
......@@ -492,23 +492,17 @@ JSTypeHintLowering::ReduceStoreKeyedOperation(const Operator* op, Node* obj,
return LoweringResult::NoChange();
}
JSTypeHintLowering::LoweringResult JSTypeHintLowering::BuildSoftDeopt(
Node* effect, Node* control, DeoptimizeReason reason) const {
Node* deoptimize = jsgraph()->graph()->NewNode(
jsgraph()->common()->Deoptimize(DeoptimizeKind::kSoft, reason,
VectorSlotPair()),
jsgraph()->Dead(), effect, control);
Node* frame_state = NodeProperties::FindFrameStateBefore(deoptimize);
deoptimize->ReplaceInput(0, frame_state);
return LoweringResult::Exit(deoptimize);
}
Node* JSTypeHintLowering::TryBuildSoftDeopt(FeedbackNexus& nexus, Node* effect,
Node* control,
DeoptimizeReason reason) const {
if ((flags() & kBailoutOnUninitialized) && nexus.IsUninitialized()) {
LoweringResult deoptimize = BuildSoftDeopt(effect, control, reason);
return deoptimize.control();
Node* deoptimize = jsgraph()->graph()->NewNode(
jsgraph()->common()->Deoptimize(DeoptimizeKind::kSoft, reason,
VectorSlotPair()),
jsgraph()->Dead(), effect, control);
Node* frame_state = NodeProperties::FindFrameStateBefore(deoptimize);
deoptimize->ReplaceInput(0, frame_state);
return deoptimize;
}
return nullptr;
}
......
......@@ -151,9 +151,6 @@ class JSTypeHintLowering {
Node* control,
FeedbackSlot slot) const;
LoweringResult BuildSoftDeopt(Node* effect, Node* control,
DeoptimizeReason reson) const;
private:
friend class JSSpeculativeBinopBuilder;
Node* TryBuildSoftDeopt(FeedbackNexus& nexus, Node* effect, Node* control,
......
......@@ -730,7 +730,6 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kJSLoadNamed:
// Type can be anything.
CheckTypeIs(node, Type::Any());
CHECK(NamedAccessOf(node->op()).feedback().IsValid());
break;
case IrOpcode::kJSLoadGlobal:
// Type can be anything.
......@@ -745,7 +744,6 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kJSStoreNamed:
// Type is empty.
CheckNotTyped(node);
CHECK(NamedAccessOf(node->op()).feedback().IsValid());
break;
case IrOpcode::kJSStoreGlobal:
// Type is empty.
......
......@@ -418,6 +418,7 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
case Bytecode::kLdaLookupSlot:
case Bytecode::kLdaGlobal:
case Bytecode::kLdaNamedProperty:
case Bytecode::kLdaNamedPropertyNoFeedback:
case Bytecode::kLdaKeyedProperty:
case Bytecode::kLdaGlobalInsideTypeof:
case Bytecode::kLdaLookupSlotInsideTypeof:
......@@ -842,6 +843,7 @@ bool BytecodeRequiresRuntimeCheck(interpreter::Bytecode bytecode) {
typedef interpreter::Bytecode Bytecode;
switch (bytecode) {
case Bytecode::kStaNamedProperty:
case Bytecode::kStaNamedPropertyNoFeedback:
case Bytecode::kStaNamedOwnProperty:
case Bytecode::kStaKeyedProperty:
case Bytecode::kStaInArrayLiteral:
......
......@@ -797,6 +797,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
Register object, const AstRawString* name) {
size_t name_index = GetConstantPoolEntry(name);
OutputLdaNamedPropertyNoFeedback(object, name_index);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
Register object, int feedback_slot) {
OutputLdaKeyedProperty(object, feedback_slot);
......@@ -847,6 +854,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedPropertyNoFeedback(
Register object, const AstRawString* name, LanguageMode language_mode) {
size_t name_index = GetConstantPoolEntry(name);
OutputStaNamedPropertyNoFeedback(object, name_index,
static_cast<uint8_t>(language_mode));
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
Register object, const AstRawString* name, int feedback_slot) {
size_t name_index = GetConstantPoolEntry(name);
......
......@@ -120,6 +120,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& LoadNamedProperty(Register object,
const AstRawString* name,
int feedback_slot);
// Named load property without feedback
BytecodeArrayBuilder& LoadNamedPropertyNoFeedback(Register object,
const AstRawString* name);
// Keyed load property. The key should be in the accumulator.
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
// Named load property of the @@iterator symbol.
......@@ -145,6 +149,12 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
const AstRawString* name,
int feedback_slot,
LanguageMode language_mode);
// Store a property named by a property name without feedback slot. The value
// to be stored should be in the accumulator.
BytecodeArrayBuilder& StoreNamedPropertyNoFeedback(
Register object, const AstRawString* name, LanguageMode language_mode);
// Store a property named by a constant from the constant pool. The value to
// be stored should be in the accumulator.
BytecodeArrayBuilder& StoreNamedProperty(Register object,
......
......@@ -2868,13 +2868,7 @@ void BytecodeGenerator::BuildLoadNamedProperty(Property* property,
Register object,
const AstRawString* name) {
if (ShouldOptimizeAsOneShot()) {
RegisterList args = register_allocator()->NewRegisterList(2);
size_t name_index = builder()->GetConstantPoolEntry(name);
builder()
->MoveRegister(object, args[0])
.LoadConstantPoolEntry(name_index)
.StoreAccumulatorInRegister(args[1])
.CallRuntime(Runtime::kInlineGetProperty, args);
builder()->LoadNamedPropertyNoFeedback(object, name);
} else {
FeedbackSlot slot = GetCachedLoadICSlot(property->obj(), name);
builder()->LoadNamedProperty(object, name, feedback_index(slot));
......@@ -2891,16 +2885,7 @@ void BytecodeGenerator::BuildStoreNamedProperty(Property* property,
}
if (ShouldOptimizeAsOneShot()) {
RegisterList args = register_allocator()->NewRegisterList(4);
size_t name_index = builder()->GetConstantPoolEntry(name);
builder()
->MoveRegister(object, args[0])
.StoreAccumulatorInRegister(args[2])
.LoadConstantPoolEntry(name_index)
.StoreAccumulatorInRegister(args[1])
.LoadLiteral(Smi::FromEnum(language_mode()))
.StoreAccumulatorInRegister(args[3])
.CallRuntime(Runtime::kSetNamedProperty, args);
builder()->StoreNamedPropertyNoFeedback(object, name, language_mode());
} else {
FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
builder()->StoreNamedProperty(object, name, feedback_index(slot),
......
......@@ -98,6 +98,8 @@ namespace interpreter {
/* Property loads (LoadIC) operations */ \
V(LdaNamedProperty, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
V(LdaNamedPropertyNoFeedback, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kIdx) \
V(LdaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
\
......@@ -110,6 +112,8 @@ namespace interpreter {
/* Propery stores (StoreIC) operations */ \
V(StaNamedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
V(StaNamedPropertyNoFeedback, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kFlag8) \
V(StaNamedOwnProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
V(StaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
......
......@@ -518,6 +518,18 @@ IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
}
}
// LdaPropertyNofeedback <object> <slot>
//
// Calls the GetProperty builtin for <object> and the key in the accumulator.
IGNITION_HANDLER(LdaNamedPropertyNoFeedback, InterpreterAssembler) {
Node* object = LoadRegisterAtOperandIndex(0);
Node* name = LoadConstantPoolEntryAtOperandIndex(1);
Node* context = GetContext();
Node* result = CallBuiltin(Builtins::kGetProperty, context, object, name);
SetAccumulator(result);
Dispatch();
}
// KeyedLoadIC <object> <slot>
//
// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
......@@ -583,6 +595,24 @@ IGNITION_HANDLER(StaNamedOwnProperty, InterpreterStoreNamedPropertyAssembler) {
StaNamedProperty(ic);
}
// StaNamedPropertyNoFeedback <object> <name_index>
//
// Calls the SetPropertyBuiltin for <object> and the name in constant pool entry
// <name_index> with the value in the accumulator.
IGNITION_HANDLER(StaNamedPropertyNoFeedback,
InterpreterStoreNamedPropertyAssembler) {
Node* object = LoadRegisterAtOperandIndex(0);
Node* name = LoadConstantPoolEntryAtOperandIndex(1);
Node* value = GetAccumulator();
Node* language_mode = SmiFromInt32(BytecodeOperandFlag(2));
Node* context = GetContext();
Node* result = CallRuntime(Runtime::kSetNamedProperty, context, object, name,
value, language_mode);
SetAccumulator(result);
Dispatch();
}
// StaKeyedProperty <object> <key> <slot>
//
// Calls the KeyedStoreIC at FeedbackVector slot <slot> for <object> and
......
......@@ -206,12 +206,6 @@ Node* IntrinsicsGenerator::HasProperty(
args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
}
Node* IntrinsicsGenerator::GetProperty(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
return IntrinsicAsStubCall(
args, context, Builtins::CallableFor(isolate(), Builtins::kGetProperty));
}
Node* IntrinsicsGenerator::RejectPromise(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
return IntrinsicAsStubCall(
......
......@@ -25,7 +25,6 @@ namespace interpreter {
V(CreateIterResultObject, create_iter_result_object, 2) \
V(CreateAsyncFromSyncIterator, create_async_from_sync_iterator, 1) \
V(HasProperty, has_property, 2) \
V(GetProperty, get_property, 2) \
V(IsArray, is_array, 1) \
V(IsJSReceiver, is_js_receiver, 1) \
V(IsSmi, is_smi, 1) \
......
......@@ -20,9 +20,9 @@ snippet: "
l['a'] = l['b'];
"
frame size: 7
frame size: 4
parameter count: 1
bytecode array length: 128
bytecode array length: 77
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(LdaConstant), U8(0),
......@@ -33,46 +33,25 @@ bytecodes: [
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
/* 60 S> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(1),
B(LdaConstant), U8(2),
B(Star), R(3),
B(Mov), R(1), R(2),
/* 65 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(2), U8(2),
/* 65 E> */ B(LdaNamedPropertyNoFeedback), R(1), U8(2),
B(Star), R(1),
/* 73 E> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(2),
B(LdaConstant), U8(3),
B(Star), R(4),
B(Mov), R(2), R(3),
/* 74 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(3), U8(2),
/* 74 E> */ B(LdaNamedPropertyNoFeedback), R(2), U8(3),
/* 71 E> */ B(Add), R(1), U8(2),
/* 62 E> */ B(StaGlobal), U8(4), U8(5),
/* 87 S> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(1),
B(LdaSmi), I8(7),
B(Star), R(4),
B(LdaConstant), U8(3),
B(Star), R(3),
B(LdaZero),
B(Star), R(5),
B(Mov), R(1), R(2),
/* 94 E> */ B(CallRuntime), U16(Runtime::kSetNamedProperty), R(2), U8(4),
/* 94 E> */ B(StaNamedPropertyNoFeedback), R(1), U8(3), U8(0),
/* 105 S> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(1),
/* 114 E> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(2),
B(LdaConstant), U8(3),
B(Star), R(4),
B(Mov), R(2), R(3),
/* 115 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(3), U8(2),
/* 115 E> */ B(LdaNamedPropertyNoFeedback), R(2), U8(3),
B(Star), R(2),
B(LdaConstant), U8(2),
B(Star), R(4),
B(LdaZero),
B(Star), R(6),
B(Mov), R(1), R(3),
B(Mov), R(2), R(5),
/* 112 E> */ B(CallRuntime), U16(Runtime::kSetNamedProperty), R(3), U8(4),
B(Mov), R(5), R(0),
/* 112 E> */ B(StaNamedPropertyNoFeedback), R(1), U8(2), U8(0),
B(Mov), R(2), R(0),
B(Ldar), R(0),
/* 128 S> */ B(Return),
]
......@@ -307,9 +286,9 @@ snippet: "
}
"
frame size: 7
frame size: 4
parameter count: 1
bytecode array length: 111
bytecode array length: 75
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(LdaConstant), U8(0),
......@@ -320,40 +299,25 @@ bytecodes: [
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
/* 63 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaConstant), U8(2),
B(Star), R(3),
B(Mov), R(1), R(2),
/* 68 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(2), U8(2),
/* 68 E> */ B(LdaNamedPropertyNoFeedback), R(1), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
/* 74 E> */ B(TestLessThan), R(1), U8(4),
B(JumpIfFalse), U8(36),
B(JumpIfFalse), U8(22),
/* 89 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
B(Star), R(2),
B(LdaConstant), U8(2),
B(Star), R(4),
B(LdaZero),
B(Star), R(6),
B(Mov), R(1), R(3),
B(Mov), R(2), R(5),
/* 96 E> */ B(CallRuntime), U16(Runtime::kSetNamedProperty), R(3), U8(4),
B(Mov), R(5), R(0),
/* 96 E> */ B(StaNamedPropertyNoFeedback), R(1), U8(2), U8(0),
B(Mov), R(2), R(0),
B(Ldar), R(2),
B(Jump), U8(34),
B(Jump), U8(20),
/* 124 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
B(Star), R(2),
B(LdaConstant), U8(3),
B(Star), R(4),
B(LdaZero),
B(Star), R(6),
B(Mov), R(1), R(3),
B(Mov), R(2), R(5),
/* 131 E> */ B(CallRuntime), U16(Runtime::kSetNamedProperty), R(3), U8(4),
B(Mov), R(5), R(0),
/* 131 E> */ B(StaNamedPropertyNoFeedback), R(1), U8(3), U8(0),
B(Mov), R(2), R(0),
B(Ldar), R(2),
B(Ldar), R(0),
/* 150 S> */ B(Return),
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-enable-one-shot-optimization
Debug = debug.Debug
var exception = null;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-enable-one-shot-optimization
Debug = debug.Debug
var exception = null;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-enable-one-shot-optimization
Debug = debug.Debug;
// StaCurrentContextSlot
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-enable-one-shot-optimization
Debug = debug.Debug
var exception = null;
......
......@@ -134,9 +134,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Emit load / store property operations.
builder.LoadNamedProperty(reg, name, load_slot.ToInt())
.LoadNamedPropertyNoFeedback(reg, name)
.LoadKeyedProperty(reg, keyed_load_slot.ToInt())
.StoreNamedProperty(reg, name, sloppy_store_slot.ToInt(),
LanguageMode::kSloppy)
.StoreNamedPropertyNoFeedback(reg, name, LanguageMode::kStrict)
.StoreNamedPropertyNoFeedback(reg, name, LanguageMode::kSloppy)
.StoreKeyedProperty(reg, reg, sloppy_keyed_store_slot.ToInt(),
LanguageMode::kSloppy)
.StoreNamedProperty(reg, name, strict_store_slot.ToInt(),
......
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