[interpreter] Bytecode for StaDataPropertyInLiteral.
Add bytecode for defining data properties, which initially just calls the runtime function. BUG=v8:5624 Review-Url: https://codereview.chromium.org/2510743002 Cr-Commit-Position: refs/heads/master@{#41101}
This commit is contained in:
parent
572b643b47
commit
f7795cbf6e
@ -792,6 +792,23 @@ void BytecodeGraphBuilder::VisitStaGlobalStrict() {
|
||||
BuildStoreGlobal(LanguageMode::STRICT);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() {
|
||||
Node* object =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
Node* name =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
|
||||
Node* value =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2));
|
||||
Node* attrs =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3));
|
||||
|
||||
Node* set_function_name = environment()->LookupAccumulator();
|
||||
const Operator* op =
|
||||
javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
|
||||
Node* store = NewNode(op, object, name, value, attrs, set_function_name);
|
||||
environment()->RecordAfterState(store, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitLdaContextSlot() {
|
||||
// TODO(mythria): immutable flag is also set to false. This information is not
|
||||
// available in bytecode array. update this code when the implementation
|
||||
|
@ -87,6 +87,12 @@ class BytecodeGraphBuilder {
|
||||
return MakeNode(op, arraysize(buffer), buffer, false);
|
||||
}
|
||||
|
||||
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
|
||||
Node* n5) {
|
||||
Node* buffer[] = {n1, n2, n3, n4, n5};
|
||||
return MakeNode(op, arraysize(buffer), buffer, false);
|
||||
}
|
||||
|
||||
// Helpers to create new control nodes.
|
||||
Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
|
||||
Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
|
||||
|
@ -542,6 +542,12 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
|
||||
Register object, Register name, Register value, Register attrs) {
|
||||
OutputStaDataPropertyInLiteral(object, name, value, attrs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
|
||||
Register object, const Handle<Name> name, int feedback_slot,
|
||||
LanguageMode language_mode) {
|
||||
|
@ -122,6 +122,13 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
|
||||
// Keyed load property. The key should be in the accumulator.
|
||||
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
|
||||
|
||||
// Store properties. Flag for NeedsSetFunctionName() should
|
||||
// be in the accumulator.
|
||||
BytecodeArrayBuilder& StoreDataPropertyInLiteral(Register object,
|
||||
Register name,
|
||||
Register value,
|
||||
Register attrs);
|
||||
|
||||
// Store properties. The value to be stored should be in the accumulator.
|
||||
BytecodeArrayBuilder& StoreNamedProperty(Register object,
|
||||
const Handle<Name> name,
|
||||
|
@ -1431,9 +1431,8 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
||||
Register literal,
|
||||
Register prototype) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
RegisterList args = register_allocator()->NewRegisterList(5);
|
||||
Register receiver = args[0], key = args[1], value = args[2], attr = args[3],
|
||||
set_function_name = args[4];
|
||||
RegisterList args = register_allocator()->NewRegisterList(4);
|
||||
Register receiver = args[0], key = args[1], value = args[2], attr = args[3];
|
||||
|
||||
bool attr_assigned = false;
|
||||
Register old_receiver = Register::invalid_value();
|
||||
@ -1480,18 +1479,15 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
||||
case ClassLiteral::Property::METHOD: {
|
||||
builder()
|
||||
->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
|
||||
.StoreAccumulatorInRegister(set_function_name)
|
||||
.CallRuntime(Runtime::kDefineDataPropertyInLiteral, args);
|
||||
.StoreDataPropertyInLiteral(receiver, key, value, attr);
|
||||
break;
|
||||
}
|
||||
case ClassLiteral::Property::GETTER: {
|
||||
builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
|
||||
args.Truncate(4));
|
||||
builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, args);
|
||||
break;
|
||||
}
|
||||
case ClassLiteral::Property::SETTER: {
|
||||
builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
|
||||
args.Truncate(4));
|
||||
builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, args);
|
||||
break;
|
||||
}
|
||||
case ClassLiteral::Property::FIELD: {
|
||||
@ -1699,18 +1695,20 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
case ObjectLiteral::Property::CONSTANT:
|
||||
case ObjectLiteral::Property::COMPUTED:
|
||||
case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
|
||||
RegisterList args = register_allocator()->NewRegisterList(5);
|
||||
builder()->MoveRegister(literal, args[0]);
|
||||
Register key = register_allocator()->NewRegister();
|
||||
VisitForAccumulatorValue(property->key());
|
||||
builder()->ConvertAccumulatorToName(args[1]);
|
||||
VisitForRegisterValue(property->value(), args[2]);
|
||||
VisitSetHomeObject(args[2], literal, property);
|
||||
builder()->ConvertAccumulatorToName(key);
|
||||
|
||||
Register value = VisitForRegisterValue(property->value());
|
||||
VisitSetHomeObject(value, literal, property);
|
||||
|
||||
Register attr = register_allocator()->NewRegister();
|
||||
|
||||
builder()
|
||||
->LoadLiteral(Smi::FromInt(NONE))
|
||||
.StoreAccumulatorInRegister(args[3])
|
||||
.StoreAccumulatorInRegister(attr)
|
||||
.LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
|
||||
.StoreAccumulatorInRegister(args[4]);
|
||||
builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, args);
|
||||
.StoreDataPropertyInLiteral(literal, key, value, attr);
|
||||
break;
|
||||
}
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
|
@ -98,6 +98,8 @@ namespace interpreter {
|
||||
OperandType::kReg, OperandType::kIdx) \
|
||||
V(StaKeyedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg, \
|
||||
OperandType::kReg, OperandType::kIdx) \
|
||||
V(StaDataPropertyInLiteral, AccumulatorUse::kRead, OperandType::kReg, \
|
||||
OperandType::kReg, OperandType::kReg, OperandType::kReg) \
|
||||
\
|
||||
/* Binary Operators */ \
|
||||
V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
|
||||
|
@ -846,6 +846,33 @@ void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) {
|
||||
DoKeyedStoreIC(ic, assembler);
|
||||
}
|
||||
|
||||
// StaDataPropertyInLiteral <object> <name> <value> <attrs>
|
||||
//
|
||||
// Define a property <name> with value <value> in <object>. Use property
|
||||
// attributes <attrs> in the definition and set the name property of <value>
|
||||
// according to the flag in the accumulator.
|
||||
//
|
||||
// This definition is not observable and is used only for definitions
|
||||
// in object or class literals.
|
||||
void Interpreter::DoStaDataPropertyInLiteral(InterpreterAssembler* assembler) {
|
||||
Node* object_reg_index = __ BytecodeOperandReg(0);
|
||||
Node* object = __ LoadRegister(object_reg_index);
|
||||
Node* name_reg_index = __ BytecodeOperandReg(1);
|
||||
Node* name = __ LoadRegister(name_reg_index);
|
||||
Node* value_reg_index = __ BytecodeOperandReg(2);
|
||||
Node* value = __ LoadRegister(value_reg_index);
|
||||
Node* attrs_reg_index = __ BytecodeOperandReg(3);
|
||||
Node* attrs = __ LoadRegister(attrs_reg_index);
|
||||
|
||||
Node* set_function_name = __ GetAccumulator();
|
||||
|
||||
Node* context = __ GetContext();
|
||||
|
||||
__ CallRuntime(Runtime::kDefineDataPropertyInLiteral, context, object, name,
|
||||
value, attrs, set_function_name);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
// LdaModuleVariable <cell_index> <depth>
|
||||
//
|
||||
// Load the contents of a module variable into the accumulator. The variable is
|
||||
|
@ -12,9 +12,9 @@ snippet: "
|
||||
speak() { console.log(this.name + ' is speaking.'); }
|
||||
}
|
||||
"
|
||||
frame size: 10
|
||||
frame size: 9
|
||||
parameter count: 1
|
||||
bytecode array length: 75
|
||||
bytecode array length: 70
|
||||
bytecodes: [
|
||||
B(LdaTheHole),
|
||||
B(Star), R(2),
|
||||
@ -40,9 +40,7 @@ bytecodes: [
|
||||
B(LdaSmi), U8(2),
|
||||
B(Star), R(8),
|
||||
B(LdaZero),
|
||||
B(Star), R(9),
|
||||
B(Mov), R(4), R(5),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
|
||||
B(StaDataPropertyInLiteral), R(4), R(6), R(7), R(8),
|
||||
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
|
||||
B(Star), R(0),
|
||||
B(Star), R(1),
|
||||
@ -66,9 +64,9 @@ snippet: "
|
||||
speak() { console.log(this.name + ' is speaking.'); }
|
||||
}
|
||||
"
|
||||
frame size: 10
|
||||
frame size: 9
|
||||
parameter count: 1
|
||||
bytecode array length: 75
|
||||
bytecode array length: 70
|
||||
bytecodes: [
|
||||
B(LdaTheHole),
|
||||
B(Star), R(2),
|
||||
@ -94,9 +92,7 @@ bytecodes: [
|
||||
B(LdaSmi), U8(2),
|
||||
B(Star), R(8),
|
||||
B(LdaZero),
|
||||
B(Star), R(9),
|
||||
B(Mov), R(4), R(5),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
|
||||
B(StaDataPropertyInLiteral), R(4), R(6), R(7), R(8),
|
||||
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
|
||||
B(Star), R(0),
|
||||
B(Star), R(1),
|
||||
@ -122,9 +118,9 @@ snippet: "
|
||||
static [n1]() { return n1; }
|
||||
}
|
||||
"
|
||||
frame size: 11
|
||||
frame size: 10
|
||||
parameter count: 1
|
||||
bytecode array length: 121
|
||||
bytecode array length: 114
|
||||
bytecodes: [
|
||||
B(CreateFunctionContext), U8(2),
|
||||
B(PushContext), R(3),
|
||||
@ -156,9 +152,7 @@ bytecodes: [
|
||||
B(LdaSmi), U8(2),
|
||||
B(Star), R(9),
|
||||
B(LdaSmi), U8(1),
|
||||
B(Star), R(10),
|
||||
B(Mov), R(5), R(6),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(6), U8(5),
|
||||
B(StaDataPropertyInLiteral), R(5), R(7), R(8), R(9),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
/* 106 E> */ B(ToName), R(7),
|
||||
B(LdaConstant), U8(3),
|
||||
@ -169,8 +163,7 @@ bytecodes: [
|
||||
B(CreateClosure), U8(5), U8(2),
|
||||
B(Star), R(8),
|
||||
B(LdaSmi), U8(1),
|
||||
B(Star), R(10),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(6), U8(5),
|
||||
B(StaDataPropertyInLiteral), R(6), R(7), R(8), R(9),
|
||||
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1),
|
||||
B(Star), R(0),
|
||||
B(Star), R(1),
|
||||
|
@ -285,24 +285,22 @@ handlers: [
|
||||
snippet: "
|
||||
var a = 'test'; return { [a]: 1 };
|
||||
"
|
||||
frame size: 7
|
||||
frame size: 5
|
||||
parameter count: 1
|
||||
bytecode array length: 33
|
||||
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(35), R(1),
|
||||
/* 60 E> */ B(ToName), R(3),
|
||||
/* 60 E> */ B(ToName), R(2),
|
||||
B(LdaSmi), U8(1),
|
||||
B(Star), R(3),
|
||||
B(LdaZero),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(LdaZero),
|
||||
B(Star), R(6),
|
||||
B(Mov), R(1), R(2),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
|
||||
B(Ldar), R(2),
|
||||
B(StaDataPropertyInLiteral), R(1), R(2), R(3), R(4),
|
||||
B(Ldar), R(1),
|
||||
/* 69 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -316,25 +314,23 @@ handlers: [
|
||||
snippet: "
|
||||
var a = 'test'; return { val: a, [a]: 1 };
|
||||
"
|
||||
frame size: 7
|
||||
frame size: 5
|
||||
parameter count: 1
|
||||
bytecode array length: 37
|
||||
bytecode array length: 32
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
B(Star), R(0),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(1), R(1),
|
||||
/* 64 E> */ B(StaNamedPropertySloppy), R(1), U8(2), U8(2),
|
||||
/* 68 E> */ B(ToName), R(3),
|
||||
/* 68 E> */ B(ToName), R(2),
|
||||
B(LdaSmi), U8(1),
|
||||
B(Star), R(3),
|
||||
B(LdaZero),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(LdaZero),
|
||||
B(Star), R(6),
|
||||
B(Mov), R(1), R(2),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
|
||||
B(Ldar), R(2),
|
||||
B(StaDataPropertyInLiteral), R(1), R(2), R(3), R(4),
|
||||
B(Ldar), R(1),
|
||||
/* 77 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -349,24 +345,23 @@ handlers: [
|
||||
snippet: "
|
||||
var a = 'test'; return { [a]: 1, __proto__: {} };
|
||||
"
|
||||
frame size: 7
|
||||
frame size: 5
|
||||
parameter count: 1
|
||||
bytecode array length: 46
|
||||
bytecode array length: 44
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
B(Star), R(0),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(1), U8(35), R(1),
|
||||
/* 60 E> */ B(ToName), R(3),
|
||||
/* 60 E> */ B(ToName), R(2),
|
||||
B(LdaSmi), U8(1),
|
||||
B(Star), R(3),
|
||||
B(LdaZero),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(LdaZero),
|
||||
B(Star), R(6),
|
||||
B(Mov), R(1), R(2),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
|
||||
B(StaDataPropertyInLiteral), R(1), R(2), R(3), R(4),
|
||||
B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(4),
|
||||
B(Mov), R(1), R(2),
|
||||
B(Mov), R(4), R(3),
|
||||
B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2),
|
||||
B(Ldar), R(2),
|
||||
@ -383,29 +378,28 @@ handlers: [
|
||||
snippet: "
|
||||
var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };
|
||||
"
|
||||
frame size: 7
|
||||
frame size: 6
|
||||
parameter count: 1
|
||||
bytecode array length: 67
|
||||
bytecode array length: 65
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
B(Star), R(0),
|
||||
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(1),
|
||||
/* 60 E> */ B(ToName), R(3),
|
||||
/* 60 E> */ B(ToName), R(2),
|
||||
B(LdaConstant), U8(2),
|
||||
B(Star), R(3),
|
||||
B(LdaZero),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(LdaZero),
|
||||
B(Star), R(6),
|
||||
B(Mov), R(1), R(2),
|
||||
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
|
||||
B(StaDataPropertyInLiteral), R(1), R(2), R(3), R(4),
|
||||
B(LdaConstant), U8(3),
|
||||
B(ToName), R(3),
|
||||
B(CreateClosure), U8(4), U8(2),
|
||||
B(Star), R(4),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(Mov), R(1), R(2),
|
||||
B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), R(2), U8(4),
|
||||
B(LdaConstant), U8(3),
|
||||
B(ToName), R(3),
|
||||
|
@ -261,7 +261,6 @@ TestNumericNamesSetter(['1.2', '1.3'], {
|
||||
set 1.30(_) {; }
|
||||
});
|
||||
|
||||
|
||||
(function TestPrototypeInObjectLiteral() {
|
||||
// The prototype chain should not be used if the definition
|
||||
// happens in the object literal.
|
||||
|
@ -302,6 +302,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
.StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
|
||||
.StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
|
||||
|
||||
builder.StoreDataPropertyInLiteral(reg, reg, reg, reg);
|
||||
|
||||
// Emit wide context operations.
|
||||
builder.LoadContextSlot(reg, 1024, 0).StoreContextSlot(reg, 1024, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user