Commit 9a594e78 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Unify global and unallocated variable access.

Unifies the global and unallocated variable type accesses given that
--global_var_shortcuts is going away. Lda/StaGlobal is modified to use
Load/StoreICs on the global object. The named LoadIC and StoreIC bytecodes
are also modified so that they take a constant pool entry index for the
name rather than a register, avoiding unecessary LdaConstant bytecodes to
be emitted.

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1419003002

Cr-Commit-Position: refs/heads/master@{#31482}
parent b0e4dce6
......@@ -249,6 +249,30 @@ void BytecodeGraphBuilder::VisitStar(
}
void BytecodeGraphBuilder::VisitLdaGlobalSloppy(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
}
void BytecodeGraphBuilder::VisitLdaGlobalStrict(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
}
void BytecodeGraphBuilder::VisitStaGlobalSloppy(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
}
void BytecodeGraphBuilder::VisitStaGlobalStrict(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
}
void BytecodeGraphBuilder::VisitLdaContextSlot(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
......
......@@ -297,6 +297,12 @@ Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
}
Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
return raw_assembler_->Load(kMachAnyTagged, context,
IntPtrConstant(Context::SlotOffset(slot_index)));
}
Node* InterpreterAssembler::LoadContextSlot(Node* context, Node* slot_index) {
Node* offset =
IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
......
......@@ -96,6 +96,7 @@ class InterpreterAssembler {
Node* LoadObjectField(Node* object, int offset);
// Load |slot_index| from |context|.
Node* LoadContextSlot(Node* context, int slot_index);
Node* LoadContextSlot(Node* context, Node* slot_index);
// Stores |value| into |slot_index| of |context|.
Node* StoreContextSlot(Node* context, Node* slot_index, Node* value);
......
......@@ -264,6 +264,32 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
size_t name_index, int feedback_slot, LanguageMode language_mode) {
Bytecode bytecode = BytecodeForLoadGlobal(language_mode);
if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
Output(bytecode, static_cast<uint8_t>(name_index),
static_cast<uint8_t>(feedback_slot));
} else {
UNIMPLEMENTED();
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
size_t name_index, int feedback_slot, LanguageMode language_mode) {
Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
Output(bytecode, static_cast<uint8_t>(name_index),
static_cast<uint8_t>(feedback_slot));
} else {
UNIMPLEMENTED();
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
int slot_index) {
DCHECK(slot_index >= 0);
......@@ -291,10 +317,12 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
Register object, int feedback_slot, LanguageMode language_mode) {
Register object, size_t name_index, int feedback_slot,
LanguageMode language_mode) {
Bytecode bytecode = BytecodeForLoadIC(language_mode);
if (FitsInIdx8Operand(feedback_slot)) {
Output(bytecode, object.ToOperand(), static_cast<uint8_t>(feedback_slot));
if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
Output(bytecode, object.ToOperand(), static_cast<uint8_t>(name_index),
static_cast<uint8_t>(feedback_slot));
} else {
UNIMPLEMENTED();
}
......@@ -315,11 +343,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
Register object, Register name, int feedback_slot,
Register object, size_t name_index, int feedback_slot,
LanguageMode language_mode) {
Bytecode bytecode = BytecodeForStoreIC(language_mode);
if (FitsInIdx8Operand(feedback_slot)) {
Output(bytecode, object.ToOperand(), name.ToOperand(),
if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
Output(bytecode, object.ToOperand(), static_cast<uint8_t>(name_index),
static_cast<uint8_t>(feedback_slot));
} else {
UNIMPLEMENTED();
......@@ -894,6 +922,40 @@ Bytecode BytecodeArrayBuilder::BytecodeForKeyedStoreIC(
}
// static
Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(
LanguageMode language_mode) {
switch (language_mode) {
case SLOPPY:
return Bytecode::kLdaGlobalSloppy;
case STRICT:
return Bytecode::kLdaGlobalStrict;
case STRONG:
UNIMPLEMENTED();
default:
UNREACHABLE();
}
return static_cast<Bytecode>(-1);
}
// static
Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
LanguageMode language_mode) {
switch (language_mode) {
case SLOPPY:
return Bytecode::kStaGlobalSloppy;
case STRICT:
return Bytecode::kStaGlobalStrict;
case STRONG:
UNIMPLEMENTED();
default:
UNREACHABLE();
}
return static_cast<Bytecode>(-1);
}
// static
bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) {
return kMinUInt8 <= value && value <= kMaxUInt8;
......
......@@ -64,6 +64,9 @@ class BytecodeArrayBuilder {
// Return true if the register |reg| represents a temporary register.
bool RegisterIsTemporary(Register reg) const;
// Gets a constant pool entry for the |object|.
size_t GetConstantPoolEntry(Handle<Object> object);
// Constant loads to accumulator.
BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
BytecodeArrayBuilder& LoadLiteral(Handle<Object> object);
......@@ -74,8 +77,10 @@ class BytecodeArrayBuilder {
BytecodeArrayBuilder& LoadFalse();
// Global loads to the accumulator and stores from the accumulator.
BytecodeArrayBuilder& LoadGlobal(int slot_index);
BytecodeArrayBuilder& StoreGlobal(int slot_index, LanguageMode language_mode);
BytecodeArrayBuilder& LoadGlobal(size_t name_index, int feedback_slot,
LanguageMode language_mode);
BytecodeArrayBuilder& StoreGlobal(size_t name_index, int feedback_slot,
LanguageMode language_mode);
// Load the object at |slot_index| in |context| into the accumulator.
BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index);
......@@ -87,14 +92,16 @@ class BytecodeArrayBuilder {
BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
// Load properties. The property name should be in the accumulator.
BytecodeArrayBuilder& LoadNamedProperty(Register object, int feedback_slot,
// Named load property.
BytecodeArrayBuilder& LoadNamedProperty(Register object, size_t name_index,
int feedback_slot,
LanguageMode language_mode);
// Keyed load property. The key should be in the accumulator.
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot,
LanguageMode language_mode);
// Store properties. The value to be stored should be in the accumulator.
BytecodeArrayBuilder& StoreNamedProperty(Register object, Register name,
BytecodeArrayBuilder& StoreNamedProperty(Register object, size_t name_index,
int feedback_slot,
LanguageMode language_mode);
BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
......@@ -184,6 +191,8 @@ class BytecodeArrayBuilder {
static Bytecode BytecodeForKeyedLoadIC(LanguageMode language_mode);
static Bytecode BytecodeForStoreIC(LanguageMode language_mode);
static Bytecode BytecodeForKeyedStoreIC(LanguageMode language_mode);
static Bytecode BytecodeForLoadGlobal(LanguageMode language_mode);
static Bytecode BytecodeForStoreGlobal(LanguageMode language_mode);
static bool FitsInIdx8Operand(int value);
static bool FitsInIdx8Operand(size_t value);
......@@ -211,8 +220,6 @@ class BytecodeArrayBuilder {
uint32_t operand_value) const;
bool LastBytecodeInSameBlock() const;
size_t GetConstantPoolEntry(Handle<Object> object);
int BorrowTemporaryRegister();
void ReturnTemporaryRegister(int reg_index);
int PrepareForConsecutiveTemporaryRegisters(size_t count);
......
......@@ -713,12 +713,10 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// contains computed properties with an uninitialized value.
if (literal_key->value()->IsInternalizedString()) {
if (property->emit_store()) {
Register name = inner_temporary_register_scope.NewRegister();
builder()
->LoadLiteral(literal_key->AsPropertyName())
.StoreAccumulatorInRegister(name);
size_t name_index =
builder()->GetConstantPoolEntry(literal_key->AsPropertyName());
VisitForAccumulatorValue(property->value());
builder()->StoreNamedProperty(literal, name,
builder()->StoreNamedProperty(literal, name_index,
feedback_index(property->GetSlot(0)),
language_mode());
} else {
......@@ -939,13 +937,8 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
}
case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
TemporaryRegisterScope temporary_register_scope(builder());
Register obj = temporary_register_scope.NewRegister();
builder()->LoadContextSlot(execution_context()->reg(),
Context::GLOBAL_OBJECT_INDEX);
builder()->StoreAccumulatorInRegister(obj);
builder()->LoadLiteral(variable->name());
builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
size_t name_index = builder()->GetConstantPoolEntry(variable->name());
builder()->LoadGlobal(name_index, feedback_index(slot), language_mode());
execution_result()->SetResultInAccumulator();
break;
}
......@@ -987,21 +980,8 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
}
case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
Register value = execution_result()->NewRegister();
Register obj = execution_result()->NewRegister();
Register name = execution_result()->NewRegister();
// TODO(rmcilroy): Investigate whether we can avoid having to stash the
// value in a register.
builder()->StoreAccumulatorInRegister(value);
builder()->LoadContextSlot(execution_context()->reg(),
Context::GLOBAL_OBJECT_INDEX);
builder()->StoreAccumulatorInRegister(obj);
builder()->LoadLiteral(variable->name());
builder()->StoreAccumulatorInRegister(name);
builder()->LoadAccumulatorWithRegister(value);
builder()->StoreNamedProperty(obj, name, feedback_index(slot),
language_mode());
size_t name_index = builder()->GetConstantPoolEntry(variable->name());
builder()->StoreGlobal(name_index, feedback_index(slot), language_mode());
break;
}
case VariableLocation::CONTEXT: {
......@@ -1023,6 +1003,7 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
void BytecodeGenerator::VisitAssignment(Assignment* expr) {
DCHECK(expr->target()->IsValidReferenceExpression());
Register object, key;
size_t name_index = kMaxUInt32;
// Left-hand side can only be a property, a global or a variable slot.
Property* property = expr->target()->AsProperty();
......@@ -1035,9 +1016,8 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
break;
case NAMED_PROPERTY: {
object = VisitForRegisterValue(property->obj());
key = execution_result()->NewRegister();
builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
builder()->StoreAccumulatorInRegister(key);
name_index = builder()->GetConstantPoolEntry(
property->key()->AsLiteral()->AsPropertyName());
break;
}
case KEYED_PROPERTY: {
......@@ -1069,7 +1049,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
break;
}
case NAMED_PROPERTY:
builder()->StoreNamedProperty(object, key, feedback_index(slot),
builder()->StoreNamedProperty(object, name_index, feedback_index(slot),
language_mode());
break;
case KEYED_PROPERTY:
......@@ -1100,8 +1080,10 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
case VARIABLE:
UNREACHABLE();
case NAMED_PROPERTY: {
builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName());
builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
size_t name_index = builder()->GetConstantPoolEntry(
expr->key()->AsLiteral()->AsPropertyName());
builder()->LoadNamedProperty(obj, name_index, feedback_index(slot),
language_mode());
break;
}
case KEYED_PROPERTY: {
......@@ -1117,6 +1099,13 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
}
void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
Property* expr) {
AccumulatorResultScope result_scope(this);
VisitPropertyLoad(obj, expr);
}
void BytecodeGenerator::VisitProperty(Property* expr) {
Register obj = VisitForRegisterValue(expr->obj());
VisitPropertyLoad(obj, expr);
......@@ -1173,13 +1162,10 @@ void BytecodeGenerator::VisitCall(Call* expr) {
if (property->IsSuperAccess()) {
UNIMPLEMENTED();
}
VisitForAccumulatorValue(property->obj());
builder()->StoreAccumulatorInRegister(receiver);
// Need a result scope here to keep our consecutive
// temporaries.
AccumulatorResultScope accumulator_execution_result(this);
// Perform a property load of the callee.
VisitPropertyLoad(receiver, property);
VisitPropertyLoadForAccumulator(receiver, property);
builder()->StoreAccumulatorInRegister(callee);
break;
}
......@@ -1273,6 +1259,8 @@ void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
// TODO(rmcilroy): Set TypeofMode to INSIDE_TYPEOF for any loadICs performed
// while visiting the expression.
VisitForAccumulatorValue(expr->expression());
builder()->TypeOf();
execution_result()->SetResultInAccumulator();
......@@ -1389,7 +1377,52 @@ void BytecodeGenerator::VisitSuperPropertyReference(
}
void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
VisitForEffect(binop->left());
Visit(binop->right());
}
void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
Expression* left = binop->left();
Expression* right = binop->right();
// Short-circuit evaluation- If it is known that left is always true,
// no need to visit right
if (left->ToBooleanIsTrue()) {
VisitForAccumulatorValue(left);
} else {
BytecodeLabel end_label;
VisitForAccumulatorValue(left);
builder()->JumpIfToBooleanTrue(&end_label);
VisitForAccumulatorValue(right);
builder()->Bind(&end_label);
}
execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
Expression* left = binop->left();
Expression* right = binop->right();
// Short-circuit evaluation- If it is known that left is always false,
// no need to visit right
if (left->ToBooleanIsFalse()) {
VisitForAccumulatorValue(left);
} else {
BytecodeLabel end_label;
VisitForAccumulatorValue(left);
builder()->JumpIfToBooleanFalse(&end_label);
VisitForAccumulatorValue(right);
builder()->Bind(&end_label);
}
execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitNewLocalFunctionContext() {
AccumulatorResultScope accumulator_execution_result(this);
Scope* scope = this->scope();
// Allocate a new local context.
......@@ -1408,6 +1441,7 @@ void BytecodeGenerator::VisitNewLocalFunctionContext() {
builder()->CallRuntime(Runtime::kNewFunctionContext,
Register::function_closure(), 1);
}
execution_result()->SetResultInAccumulator();
}
......@@ -1436,6 +1470,7 @@ void BytecodeGenerator::VisitBuildLocalActivationContext() {
void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
AccumulatorResultScope accumulator_execution_result(this);
DCHECK(scope->is_block_scope());
// Allocate a new local block context.
......@@ -1450,49 +1485,6 @@ void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
builder()
->StoreAccumulatorInRegister(closure)
.CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
}
void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
VisitForEffect(binop->left());
Visit(binop->right());
}
void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
Expression* left = binop->left();
Expression* right = binop->right();
// Short-circuit evaluation- If it is known that left is always true,
// no need to visit right
if (left->ToBooleanIsTrue()) {
VisitForAccumulatorValue(left);
} else {
BytecodeLabel end_label;
VisitForAccumulatorValue(left);
builder()->JumpIfToBooleanTrue(&end_label);
VisitForAccumulatorValue(right);
builder()->Bind(&end_label);
}
execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
Expression* left = binop->left();
Expression* right = binop->right();
// Short-circuit evaluation- If it is known that left is always false,
// no need to visit right
if (left->ToBooleanIsFalse()) {
VisitForAccumulatorValue(left);
} else {
BytecodeLabel end_label;
VisitForAccumulatorValue(left);
builder()->JumpIfToBooleanFalse(&end_label);
VisitForAccumulatorValue(right);
builder()->Bind(&end_label);
}
execution_result()->SetResultInAccumulator();
}
......@@ -1516,23 +1508,12 @@ void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
Expression* expr = property->value();
if (!FunctionLiteral::NeedsHomeObject(expr)) return;
// TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the
// home object.
UNIMPLEMENTED();
TemporaryRegisterScope temporary_register_scope(builder());
Register name = temporary_register_scope.NewRegister();
isolate()->factory()->home_object_symbol();
builder()
->LoadLiteral(isolate()->factory()->home_object_symbol())
.StoreAccumulatorInRegister(name)
.StoreNamedProperty(home_object, name,
feedback_index(property->GetSlot(slot_number)),
language_mode());
}
void BytecodeGenerator::VisitFunctionClosureForContext() {
AccumulatorResultScope accumulator_execution_result(this);
Scope* closure_scope = execution_context()->scope()->ClosureScope();
if (closure_scope->is_script_scope() ||
closure_scope->is_module_scope()) {
......@@ -1544,6 +1525,7 @@ void BytecodeGenerator::VisitFunctionClosureForContext() {
DCHECK(closure_scope->is_function_scope());
builder()->LoadAccumulatorWithRegister(Register::function_closure());
}
execution_result()->SetResultInAccumulator();
}
......
......@@ -42,13 +42,18 @@ class BytecodeGenerator : public AstVisitor {
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
Register VisitArguments(ZoneList<Expression*>* arguments);
void VisitArithmeticExpression(BinaryOperation* binop);
void VisitCommaExpression(BinaryOperation* binop);
void VisitLogicalOrExpression(BinaryOperation* binop);
void VisitLogicalAndExpression(BinaryOperation* binop);
void VisitPropertyLoad(Register obj, Property* expr);
void VisitPropertyLoadForAccumulator(Register obj, Property* expr);
void VisitVariableLoad(Variable* variable, FeedbackVectorSlot slot);
void VisitVariableAssignment(Variable* variable, FeedbackVectorSlot slot);
void VisitNewLocalFunctionContext();
void VisitBuildLocalActivationContext();
void VisitNewLocalBlockContext(Scope* scope);
......
......@@ -43,6 +43,12 @@ namespace interpreter {
V(LdaTrue, OperandType::kNone) \
V(LdaFalse, OperandType::kNone) \
\
/* Globals */ \
V(LdaGlobalSloppy, OperandType::kIdx8, OperandType::kIdx8) \
V(LdaGlobalStrict, OperandType::kIdx8, OperandType::kIdx8) \
V(StaGlobalSloppy, OperandType::kIdx8, OperandType::kIdx8) \
V(StaGlobalStrict, OperandType::kIdx8, OperandType::kIdx8) \
\
/* Context operations */ \
V(PushContext, OperandType::kReg8) \
V(PopContext, OperandType::kReg8) \
......@@ -54,14 +60,14 @@ namespace interpreter {
V(Star, OperandType::kReg8) \
\
/* LoadIC operations */ \
V(LoadICSloppy, OperandType::kReg8, OperandType::kIdx8) \
V(LoadICStrict, OperandType::kReg8, OperandType::kIdx8) \
V(LoadICSloppy, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \
V(LoadICStrict, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \
V(KeyedLoadICSloppy, OperandType::kReg8, OperandType::kIdx8) \
V(KeyedLoadICStrict, OperandType::kReg8, OperandType::kIdx8) \
\
/* StoreIC operations */ \
V(StoreICSloppy, OperandType::kReg8, OperandType::kReg8, OperandType::kIdx8) \
V(StoreICStrict, OperandType::kReg8, OperandType::kReg8, OperandType::kIdx8) \
V(StoreICSloppy, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \
V(StoreICStrict, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \
V(KeyedStoreICSloppy, OperandType::kReg8, OperandType::kReg8, \
OperandType::kIdx8) \
V(KeyedStoreICStrict, OperandType::kReg8, OperandType::kReg8, \
......
......@@ -184,6 +184,92 @@ void Interpreter::DoStar(compiler::InterpreterAssembler* assembler) {
}
void Interpreter::DoLoadGlobal(Callable ic,
compiler::InterpreterAssembler* assembler) {
// Get the global object.
Node* context = __ GetContext();
Node* global = __ LoadContextSlot(context, Context::GLOBAL_OBJECT_INDEX);
// Load the global via the LoadIC.
Node* code_target = __ HeapConstant(ic.code());
Node* constant_index = __ BytecodeOperandIdx8(0);
Node* name = __ LoadConstantPoolEntry(constant_index);
Node* raw_slot = __ BytecodeOperandIdx8(1);
Node* smi_slot = __ SmiTag(raw_slot);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* result = __ CallIC(ic.descriptor(), code_target, global, name, smi_slot,
type_feedback_vector);
__ SetAccumulator(result);
__ Dispatch();
}
// LdaGlobalSloppy <name_index> <slot>
//
// Load the global with name in constant pool entry <name_index> into the
// accumulator using FeedBackVector slot <slot> in sloppy mode.
void Interpreter::DoLdaGlobalSloppy(compiler::InterpreterAssembler* assembler) {
Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
SLOPPY, UNINITIALIZED);
DoLoadGlobal(ic, assembler);
}
// LdaGlobalSloppy <name_index> <slot>
//
// Load the global with name in constant pool entry <name_index> into the
// accumulator using FeedBackVector slot <slot> in strict mode.
void Interpreter::DoLdaGlobalStrict(compiler::InterpreterAssembler* assembler) {
Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
STRICT, UNINITIALIZED);
DoLoadGlobal(ic, assembler);
}
void Interpreter::DoStoreGlobal(Callable ic,
compiler::InterpreterAssembler* assembler) {
// Get the global object.
Node* context = __ GetContext();
Node* global = __ LoadContextSlot(context, Context::GLOBAL_OBJECT_INDEX);
// Store the global via the StoreIC.
Node* code_target = __ HeapConstant(ic.code());
Node* constant_index = __ BytecodeOperandIdx8(0);
Node* name = __ LoadConstantPoolEntry(constant_index);
Node* value = __ GetAccumulator();
Node* raw_slot = __ BytecodeOperandIdx8(1);
Node* smi_slot = __ SmiTag(raw_slot);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
__ CallIC(ic.descriptor(), code_target, global, name, value, smi_slot,
type_feedback_vector);
__ Dispatch();
}
// StaGlobalSloppy <name_index> <slot>
//
// Store the value in the accumulator into the global with name in constant pool
// entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
void Interpreter::DoStaGlobalSloppy(compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
DoStoreGlobal(ic, assembler);
}
// StaGlobalStrict <name_index> <slot>
//
// Store the value in the accumulator into the global with name in constant pool
// entry <name_index> using FeedBackVector slot <slot> in strict mode.
void Interpreter::DoStaGlobalStrict(compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
DoStoreGlobal(ic, assembler);
}
// LdaContextSlot <context> <slot_index>
//
// Load the object in |slot_index| of |context| into the accumulator.
......@@ -210,13 +296,14 @@ void Interpreter::DoStaContextSlot(compiler::InterpreterAssembler* assembler) {
}
void Interpreter::DoPropertyLoadIC(Callable ic,
void Interpreter::DoLoadIC(Callable ic,
compiler::InterpreterAssembler* assembler) {
Node* code_target = __ HeapConstant(ic.code());
Node* reg_index = __ BytecodeOperandReg8(0);
Node* object = __ LoadRegister(reg_index);
Node* name = __ GetAccumulator();
Node* raw_slot = __ BytecodeOperandIdx8(1);
Node* register_index = __ BytecodeOperandReg8(0);
Node* object = __ LoadRegister(register_index);
Node* constant_index = __ BytecodeOperandIdx8(1);
Node* name = __ LoadConstantPoolEntry(constant_index);
Node* raw_slot = __ BytecodeOperandIdx8(2);
Node* smi_slot = __ SmiTag(raw_slot);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* result = __ CallIC(ic.descriptor(), code_target, object, name, smi_slot,
......@@ -226,25 +313,41 @@ void Interpreter::DoPropertyLoadIC(Callable ic,
}
// LoadICSloppy <object> <slot>
// LoadICSloppy <object> <name_index> <slot>
//
// Calls the sloppy mode LoadIC at FeedBackVector slot <slot> for <object> and
// the name in the accumulator.
// the name at constant pool entry <name_index>.
void Interpreter::DoLoadICSloppy(compiler::InterpreterAssembler* assembler) {
Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
SLOPPY, UNINITIALIZED);
DoPropertyLoadIC(ic, assembler);
DoLoadIC(ic, assembler);
}
// LoadICStrict <object> <slot>
// LoadICStrict <object> <name_index> <slot>
//
// Calls the strict mode LoadIC at FeedBackVector slot <slot> for <object> and
// the name in the accumulator.
// Calls the sloppy mode LoadIC at FeedBackVector slot <slot> for <object> and
// the name at constant pool entry <name_index>.
void Interpreter::DoLoadICStrict(compiler::InterpreterAssembler* assembler) {
Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
STRICT, UNINITIALIZED);
DoPropertyLoadIC(ic, assembler);
DoLoadIC(ic, assembler);
}
void Interpreter::DoKeyedLoadIC(Callable ic,
compiler::InterpreterAssembler* assembler) {
Node* code_target = __ HeapConstant(ic.code());
Node* reg_index = __ BytecodeOperandReg8(0);
Node* object = __ LoadRegister(reg_index);
Node* name = __ GetAccumulator();
Node* raw_slot = __ BytecodeOperandIdx8(1);
Node* smi_slot = __ SmiTag(raw_slot);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* result = __ CallIC(ic.descriptor(), code_target, object, name, smi_slot,
type_feedback_vector);
__ SetAccumulator(result);
__ Dispatch();
}
......@@ -256,7 +359,7 @@ void Interpreter::DoKeyedLoadICSloppy(
compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::KeyedLoadICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
DoPropertyLoadIC(ic, assembler);
DoKeyedLoadIC(ic, assembler);
}
......@@ -268,47 +371,65 @@ void Interpreter::DoKeyedLoadICStrict(
compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::KeyedLoadICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
DoPropertyLoadIC(ic, assembler);
DoKeyedLoadIC(ic, assembler);
}
void Interpreter::DoPropertyStoreIC(Callable ic,
void Interpreter::DoStoreIC(Callable ic,
compiler::InterpreterAssembler* assembler) {
Node* code_target = __ HeapConstant(ic.code());
Node* object_reg_index = __ BytecodeOperandReg8(0);
Node* object = __ LoadRegister(object_reg_index);
Node* name_reg_index = __ BytecodeOperandReg8(1);
Node* name = __ LoadRegister(name_reg_index);
Node* constant_index = __ BytecodeOperandIdx8(1);
Node* name = __ LoadConstantPoolEntry(constant_index);
Node* value = __ GetAccumulator();
Node* raw_slot = __ BytecodeOperandIdx8(2);
Node* smi_slot = __ SmiTag(raw_slot);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Node* result = __ CallIC(ic.descriptor(), code_target, object, name, value,
smi_slot, type_feedback_vector);
__ SetAccumulator(result);
__ CallIC(ic.descriptor(), code_target, object, name, value, smi_slot,
type_feedback_vector);
__ Dispatch();
}
// StoreICSloppy <object> <name> <slot>
// StoreICSloppy <object> <name_index> <slot>
//
// Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
// the name <name> with the value in the accumulator.
// the name in constant pool entry <name_index> with the value in the
// accumulator.
void Interpreter::DoStoreICSloppy(compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
DoPropertyStoreIC(ic, assembler);
DoStoreIC(ic, assembler);
}
// StoreICStrict <object> <name> <slot>
// StoreICStrict <object> <name_index> <slot>
//
// Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
// the name <name> with the value in the accumulator.
// the name in constant pool entry <name_index> with the value in the
// accumulator.
void Interpreter::DoStoreICStrict(compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
DoPropertyStoreIC(ic, assembler);
DoStoreIC(ic, assembler);
}
void Interpreter::DoKeyedStoreIC(Callable ic,
compiler::InterpreterAssembler* assembler) {
Node* code_target = __ HeapConstant(ic.code());
Node* object_reg_index = __ BytecodeOperandReg8(0);
Node* object = __ LoadRegister(object_reg_index);
Node* name_reg_index = __ BytecodeOperandReg8(1);
Node* name = __ LoadRegister(name_reg_index);
Node* value = __ GetAccumulator();
Node* raw_slot = __ BytecodeOperandIdx8(2);
Node* smi_slot = __ SmiTag(raw_slot);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
__ CallIC(ic.descriptor(), code_target, object, name, value, smi_slot,
type_feedback_vector);
__ Dispatch();
}
......@@ -320,7 +441,7 @@ void Interpreter::DoKeyedStoreICSloppy(
compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
DoPropertyStoreIC(ic, assembler);
DoKeyedStoreIC(ic, assembler);
}
......@@ -332,7 +453,7 @@ void Interpreter::DoKeyedStoreICStrict(
compiler::InterpreterAssembler* assembler) {
Callable ic =
CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
DoPropertyStoreIC(ic, assembler);
DoKeyedStoreIC(ic, assembler);
}
......
......@@ -59,12 +59,23 @@ class Interpreter {
void DoCompareOp(Token::Value compare_op,
compiler::InterpreterAssembler* assembler);
// Generates code to perform a property load via |ic|.
void DoPropertyLoadIC(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code to perform a global load via |ic|.
void DoLoadGlobal(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code to perform a property store via |ic|.
void DoPropertyStoreIC(Callable ic,
compiler::InterpreterAssembler* assembler);
// Generates code to perform a global store via |ic|.
void DoStoreGlobal(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code to perform a named property load via |ic|.
void DoLoadIC(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code to perform a keyed property load via |ic|.
void DoKeyedLoadIC(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code to perform a namedproperty store via |ic|.
void DoStoreIC(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code to perform a keyed property store via |ic|.
void DoKeyedStoreIC(Callable ic, compiler::InterpreterAssembler* assembler);
// Generates code ro create a literal via |function_id|.
void DoCreateLiteral(Runtime::FunctionId function_id,
......
......@@ -730,10 +730,9 @@ TEST(PropertyLoads) {
{"function f(a) { return a.name; }\nf({name : \"test\"})",
0,
2,
6,
5,
{
B(LdaConstant), U8(0), //
B(LoadICSloppy), A(1, 2), U8(vector->GetIndex(slot1)), //
B(LoadICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
......@@ -741,10 +740,9 @@ TEST(PropertyLoads) {
{"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})",
0,
2,
6,
5,
{
B(LdaConstant), U8(0), //
B(LoadICSloppy), A(1, 2), U8(vector->GetIndex(slot1)), //
B(LoadICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
......@@ -773,10 +771,9 @@ TEST(PropertyLoads) {
"f({\"-124\" : \"test\", name : 123 })",
kPointerSize,
2,
13,
12,
{
B(LdaConstant), U8(0), //
B(LoadICSloppy), A(1, 2), U8(vector->GetIndex(slot1)), //
B(LoadICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(LdaSmi8), U8(-124), //
B(KeyedLoadICSloppy), A(1, 2), U8(vector->GetIndex(slot2)), //
......@@ -787,15 +784,15 @@ TEST(PropertyLoads) {
{"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})",
0,
2,
6,
5,
{
B(LdaConstant), U8(0), //
B(LoadICStrict), A(1, 2), U8(vector->GetIndex(slot1)), //
B(LoadICStrict), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
{"name"}},
{"function f(a, b) { \"use strict\"; return a[b]; }\n"
{
"function f(a, b) { \"use strict\"; return a[b]; }\n"
"f({arg : \"test\"}, \"arg\")",
0,
3,
......@@ -829,28 +826,24 @@ TEST(PropertyStores) {
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})",
kPointerSize,
0,
2,
12,
8,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(StoreICSloppy), A(1, 2), R(0), U8(vector->GetIndex(slot1)), //
B(StoreICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return), //
},
2,
{"name", "val"}},
{"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})",
kPointerSize,
0,
2,
12,
8,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(StoreICSloppy), A(1, 2), R(0), U8(vector->GetIndex(slot1)), //
B(StoreICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return), //
},
......@@ -864,8 +857,8 @@ TEST(PropertyStores) {
B(LdaSmi8), U8(100), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(KeyedStoreICSloppy), //
A(1, 2), R(0), U8(vector->GetIndex(slot1)), //
B(KeyedStoreICSloppy), A(1, 2), R(0), //
U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return), //
},
......@@ -877,8 +870,8 @@ TEST(PropertyStores) {
8,
{
B(LdaConstant), U8(0), //
B(KeyedStoreICSloppy), //
A(1, 3), A(2, 3), U8(vector->GetIndex(slot1)), //
B(KeyedStoreICSloppy), A(1, 3), A(2, 3), //
U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return), //
},
......@@ -886,15 +879,13 @@ TEST(PropertyStores) {
{"val"}},
{"function f(a) { a.name = a[-124]; }\n"
"f({\"-124\" : \"test\", name : 123 })",
kPointerSize,
0,
2,
15,
11,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaSmi8), U8(-124), //
B(KeyedLoadICSloppy), A(1, 2), U8(vector->GetIndex(slot1)), //
B(StoreICSloppy), A(1, 2), R(0), U8(vector->GetIndex(slot2)), //
B(StoreICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot2)), //
B(LdaUndefined), //
B(Return), //
},
......@@ -902,14 +893,12 @@ TEST(PropertyStores) {
{"name"}},
{"function f(a) { \"use strict\"; a.name = \"val\"; }\n"
"f({name : \"test\"})",
kPointerSize,
0,
2,
12,
8,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(StoreICStrict), A(1, 2), R(0), U8(vector->GetIndex(slot1)), //
B(StoreICStrict), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return), //
},
......@@ -957,12 +946,11 @@ TEST(PropertyCall) {
{"function f(a) { return a.func(); }\nf(" FUNC_ARG ")",
2 * kPointerSize,
2,
16,
15,
{
B(Ldar), A(1, 2), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Call), R(0), R(1), U8(0), //
B(Return), //
......@@ -972,12 +960,11 @@ TEST(PropertyCall) {
{"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)",
4 * kPointerSize,
4,
24,
23,
{
B(Ldar), A(1, 4), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Ldar), A(2, 4), //
B(Star), R(2), //
......@@ -991,12 +978,11 @@ TEST(PropertyCall) {
{"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)",
4 * kPointerSize,
3,
26,
25,
{
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
B(Add), A(2, 3), //
......@@ -1021,52 +1007,59 @@ TEST(LoadGlobal) {
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
ExpectedSnippet<InstanceType> snippets[] = {
{
"var a = 1;\nfunction f() { return a; }\nf()",
kPointerSize,
ExpectedSnippet<const char*> snippets[] = {
{"var a = 1;\nfunction f() { return a; }\nf()",
0,
1,
11,
4,
{
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
},
{"a"}},
{"function t() { }\nfunction f() { return t; }\nf()",
0,
1,
4,
{
"function t() { }\nfunction f() { return t; }\nf()",
kPointerSize,
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
11,
{"t"}},
{"'use strict'; var a = 1;\nfunction f() { return a; }\nf()",
0,
1,
4,
{
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
{"a"}},
{"a = 1;\nfunction f() { return a; }\nf()",
0,
1,
4,
{
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{"a"}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array, true);
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
......@@ -1076,82 +1069,67 @@ TEST(StoreGlobal) {
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot();
FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot();
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
ExpectedSnippet<InstanceType> snippets[] = {
{
"var a = 1;\nfunction f() { a = 2; }\nf()",
3 * kPointerSize,
ExpectedSnippet<const char*> snippets[] = {
{"var a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
21,
7,
{
B(LdaSmi8), U8(2), //
B(Star), R(0), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot1)), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
},
{
"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")",
3 * kPointerSize,
{"a"}},
{"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")",
0,
2,
21,
7,
{
B(Ldar), R(helper.kLastParamIndex), //
B(Star), R(0), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot1)), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
},
{
"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()",
3 * kPointerSize,
{"a"}},
{"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
21,
7,
{
B(LdaSmi8), U8(2), //
B(Star), R(0), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICStrict), R(1), R(2), U8(vector->GetIndex(slot1)), //
B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
{"a"}},
{"a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
7,
{
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
B(Return) //
},
1,
{"a"}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array, true);
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
......@@ -1161,49 +1139,37 @@ TEST(CallGlobal) {
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
USE(slot1);
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
ExpectedSnippet<InstanceType> snippets[] = {
{
"function t() { }\nfunction f() { return t(); }\nf()",
3 * kPointerSize,
ExpectedSnippet<const char*> snippets[] = {
{"function t() { }\nfunction f() { return t(); }\nf()",
2 * kPointerSize,
1,
20,
13,
{
B(LdaUndefined), //
B(Star), R(1), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(2), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(2), U8(vector->GetIndex(slot2)), //
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Call), R(0), R(1), U8(0), //
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
},
{
"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()",
{"t"}},
{"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()",
5 * kPointerSize,
1,
32,
25,
{
B(LdaUndefined), //
B(Star), R(1), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(2), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(2), U8(vector->GetIndex(slot2)), //
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
......@@ -1215,116 +1181,11 @@ TEST(CallGlobal) {
B(Return) //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE},
},
{"t"}},
};
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array, true);
}
}
TEST(LoadUnallocated) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
ExpectedSnippet<const char*> snippets[] = {
{"a = 1;\nfunction f() { return a; }\nf()",
1 * kPointerSize,
1,
11,
{B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
B(Return)},
1,
{"a"}},
{"function f() { return t; }\nt = 1;\nf()",
1 * kPointerSize,
1,
11,
{B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
B(Return)},
1,
{"t"}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
TEST(StoreUnallocated) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot();
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
ExpectedSnippet<const char*> snippets[] = {
{"a = 1;\nfunction f() { a = 2; }\nf()",
3 * kPointerSize,
1,
21,
{B(LdaSmi8), U8(2), //
B(Star), R(0), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return)},
1,
{"a"}},
{"function f() { t = 4; }\nf()\nt = 1;",
3 * kPointerSize,
1,
21,
{B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot1)), //
B(LdaUndefined), //
B(Return)},
1,
{"t"}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
......@@ -1555,24 +1416,20 @@ TEST(DeclareGlobals) {
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
// Create different feedback vector specs to be precise on slot numbering.
FeedbackVectorSpec feedback_spec_ss(&zone);
FeedbackVectorSlot slot_ss_1 = feedback_spec_ss.AddStoreICSlot();
FeedbackVectorSlot slot_ss_2 = feedback_spec_ss.AddStoreICSlot();
USE(slot_ss_1);
Handle<i::TypeFeedbackVector> vector_ss =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_ss);
FeedbackVectorSpec feedback_spec_stores(&zone);
FeedbackVectorSlot store_slot_1 = feedback_spec_stores.AddStoreICSlot();
FeedbackVectorSlot store_slot_2 = feedback_spec_stores.AddStoreICSlot();
USE(store_slot_1);
FeedbackVectorSpec feedback_spec_l(&zone);
FeedbackVectorSlot slot_l_1 = feedback_spec_l.AddLoadICSlot();
Handle<i::TypeFeedbackVector> store_vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_stores);
Handle<i::TypeFeedbackVector> vector_l =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_l);
FeedbackVectorSpec feedback_spec_loads(&zone);
FeedbackVectorSlot load_slot_1 = feedback_spec_loads.AddLoadICSlot();
Handle<i::TypeFeedbackVector> load_vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads);
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1;",
......@@ -1591,8 +1448,7 @@ TEST(DeclareGlobals) {
B(Star), R(2), //
B(LdaSmi8), U8(1), //
B(Star), R(3), //
B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), //
U8(3), //
B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
B(LdaUndefined), //
B(Return) //
},
......@@ -1617,7 +1473,7 @@ TEST(DeclareGlobals) {
{"var a = 1;\na=2;",
4 * kPointerSize,
1,
52,
38,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
......@@ -1630,16 +1486,10 @@ TEST(DeclareGlobals) {
B(Star), R(2), //
B(LdaSmi8), U8(1), //
B(Star), R(3), //
B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), //
U8(3), //
B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(2), //
B(LdaConstant), U8(1), //
B(Star), R(3), //
B(Ldar), R(1), //
B(StoreICSloppy), R(2), R(3), U8(vector_ss->GetIndex(slot_ss_2)), //
B(StaGlobalSloppy), U8(1), //
U8(store_vector->GetIndex(store_slot_2)), //
B(Star), R(0), //
B(Ldar), R(0), //
B(Return) //
......@@ -1648,9 +1498,9 @@ TEST(DeclareGlobals) {
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"function f() {}\nf();",
4 * kPointerSize,
3 * kPointerSize,
1,
36,
29,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
......@@ -1659,10 +1509,8 @@ TEST(DeclareGlobals) {
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
B(LdaUndefined), //
B(Star), R(2), //
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(3), //
B(LdaConstant), U8(1), //
B(LoadICSloppy), R(3), U8(vector_l->GetIndex(slot_l_1)), //
B(LdaGlobalSloppy), U8(1), //
U8(load_vector->GetIndex(load_slot_1)), //
B(Star), R(1), //
B(Call), R(1), R(2), U8(0), //
B(Star), R(0), //
......@@ -2105,15 +1953,14 @@ TEST(RegExpLiterals) {
{"return /ab+d/.exec('abdd');",
3 * kPointerSize,
1,
27,
26,
{
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(LdaConstant), U8(1), //
B(CreateRegExpLiteral), U8(0), R(2), //
B(Star), R(1), //
B(LdaConstant), U8(2), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LoadICSloppy), R(1), U8(2), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaConstant), U8(3), //
B(Star), R(2), //
......@@ -2247,6 +2094,13 @@ TEST(ArrayLiterals) {
TEST(ObjectLiterals) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
Zone zone;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot();
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
int simple_flags = ObjectLiteral::kFastElements |
ObjectLiteral::kShallowProperties |
......@@ -2277,19 +2131,17 @@ TEST(ObjectLiterals) {
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 1; return { name: 'string', val: a };",
3 * kPointerSize,
2 * kPointerSize,
1,
24,
20,
{
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
B(LdaConstant), U8(1), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), R(2), U8(3), //
B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Ldar), R(1), //
B(Return), //
},
......@@ -2297,20 +2149,18 @@ TEST(ObjectLiterals) {
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"var a = 1; return { val: a, val: a + 1 };",
3 * kPointerSize,
2 * kPointerSize,
1,
26,
22,
{
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
B(LdaConstant), U8(1), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
B(Add), R(0), //
B(StoreICSloppy), R(1), R(2), U8(3), //
B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Ldar), R(1), //
B(Return), //
},
......@@ -2318,18 +2168,16 @@ TEST(ObjectLiterals) {
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"return { func: function() { } };",
2 * kPointerSize,
1 * kPointerSize,
1,
22,
18,
{
B(LdaConstant), U8(0), //
B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaConstant), U8(2), //
B(CreateClosure), U8(0), //
B(StoreICSloppy), R(0), R(1), U8(3), //
B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
B(Ldar), R(0), //
B(Return), //
},
......@@ -2338,18 +2186,16 @@ TEST(ObjectLiterals) {
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return { func(a) { return a; } };",
2 * kPointerSize,
1 * kPointerSize,
1,
22,
18,
{
B(LdaConstant), U8(0), //
B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaConstant), U8(2), //
B(CreateClosure), U8(0), //
B(StoreICSloppy), R(0), R(1), U8(3), //
B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
B(Ldar), R(0), //
B(Return), //
},
......@@ -2502,17 +2348,15 @@ TEST(ObjectLiterals) {
{"var a = 'test'; return { val: a, [a]: 1 }",
5 * kPointerSize,
1,
41,
37,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
B(LdaConstant), U8(2), //
B(Star), R(2), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), R(2), U8(3), //
B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)), //
B(Ldar), R(0), //
B(ToName), //
B(Star), R(2), //
......@@ -2626,9 +2470,9 @@ TEST(TopLevelObjectLiterals) {
ObjectLiteral::kDisableMementos;
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = { func: function() { } };",
6 * kPointerSize,
5 * kPointerSize,
1,
54,
50,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
......@@ -2642,11 +2486,9 @@ TEST(TopLevelObjectLiterals) {
B(LdaConstant), U8(2), //
B(CreateObjectLiteral), U8(0), U8(has_function_flags), //
B(Star), R(4), //
B(LdaConstant), U8(3), //
B(Star), R(5), //
B(LdaConstant), U8(4), //
B(CreateClosure), U8(1), //
B(StoreICSloppy), R(4), R(5), U8(5), //
B(StoreICSloppy), R(4), U8(3), U8(5), //
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), //
B(Ldar), R(4), //
B(Star), R(3), //
......@@ -2798,9 +2640,6 @@ TEST(CallNew) {
BytecodeGeneratorHelper helper;
Zone zone;
int context_reg = Register::function_context().index();
int global_index = Context::GLOBAL_OBJECT_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddGeneralSlot();
FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
......@@ -2813,14 +2652,11 @@ TEST(CallNew) {
{"function bar() { this.value = 0; }\n"
"function f() { return new bar(); }\n"
"f()",
2 * kPointerSize,
1 * kPointerSize,
1,
17,
10,
{
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(New), R(0), R(0), U8(0), //
B(Return), //
......@@ -2832,12 +2668,9 @@ TEST(CallNew) {
"f()",
2 * kPointerSize,
1,
21,
14,
{
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
......@@ -2856,12 +2689,9 @@ TEST(CallNew) {
"f()",
4 * kPointerSize,
1,
29,
22,
{
B(LdaContextSlot), R(context_reg), U8(global_index), //
B(Star), R(1), //
B(LdaConstant), U8(0), //
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
......
......@@ -780,9 +780,9 @@ TEST(InterpreterLoadNamedProperty) {
builder.set_locals_count(0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name)
.LoadNamedProperty(builder.Parameter(0), vector->GetIndex(slot),
i::SLOPPY)
size_t name_index = builder.GetConstantPoolEntry(name);
builder.LoadNamedProperty(builder.Parameter(0), name_index,
vector->GetIndex(slot), i::SLOPPY)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
......@@ -879,13 +879,12 @@ TEST(InterpreterStoreNamedProperty) {
name = factory->string_table()->LookupString(isolate, name);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
builder.set_locals_count(1);
builder.set_locals_count(0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name)
.StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(999))
.StoreNamedProperty(builder.Parameter(0), Register(0),
size_t name_index = builder.GetConstantPoolEntry(name);
builder.LoadLiteral(Smi::FromInt(999))
.StoreNamedProperty(builder.Parameter(0), name_index,
vector->GetIndex(slot), i::STRICT)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
......@@ -998,8 +997,9 @@ TEST(InterpreterCall) {
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name)
.LoadNamedProperty(builder.Parameter(0), slot_index, i::SLOPPY)
size_t name_index = builder.GetConstantPoolEntry(name);
builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index,
i::SLOPPY)
.StoreAccumulatorInRegister(Register(0))
.Call(Register(0), builder.Parameter(0), 0)
.Return();
......@@ -1020,8 +1020,9 @@ TEST(InterpreterCall) {
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name)
.LoadNamedProperty(builder.Parameter(0), slot_index, i::SLOPPY)
size_t name_index = builder.GetConstantPoolEntry(name);
builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index,
i::SLOPPY)
.StoreAccumulatorInRegister(Register(0))
.Call(Register(0), builder.Parameter(0), 0)
.Return();
......@@ -1045,8 +1046,9 @@ TEST(InterpreterCall) {
builder.set_locals_count(4);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name)
.LoadNamedProperty(builder.Parameter(0), slot_index, i::SLOPPY)
size_t name_index = builder.GetConstantPoolEntry(name);
builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index,
i::SLOPPY)
.StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
.StoreAccumulatorInRegister(Register(1))
......@@ -1075,8 +1077,9 @@ TEST(InterpreterCall) {
builder.set_locals_count(12);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name)
.LoadNamedProperty(builder.Parameter(0), slot_index, i::SLOPPY)
size_t name_index = builder.GetConstantPoolEntry(name);
builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index,
i::SLOPPY)
.StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
.StoreAccumulatorInRegister(Register(1))
......
......@@ -43,6 +43,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
Register reg(0);
builder.LoadAccumulatorWithRegister(reg).StoreAccumulatorInRegister(reg);
// Emit global load / store operations.
builder.LoadGlobal(0, 1, LanguageMode::SLOPPY)
.LoadGlobal(0, 1, LanguageMode::STRICT)
.StoreGlobal(0, 1, LanguageMode::SLOPPY)
.StoreGlobal(0, 1, LanguageMode::STRICT);
// Emit context operations.
builder.PushContext(reg);
builder.PopContext(reg);
......@@ -50,13 +56,13 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.StoreContextSlot(reg, 1);
// Emit load / store property operations.
builder.LoadNamedProperty(reg, 0, LanguageMode::SLOPPY)
builder.LoadNamedProperty(reg, 0, 0, LanguageMode::SLOPPY)
.LoadKeyedProperty(reg, 0, LanguageMode::SLOPPY)
.StoreNamedProperty(reg, reg, 0, LanguageMode::SLOPPY)
.StoreNamedProperty(reg, 0, 0, LanguageMode::SLOPPY)
.StoreKeyedProperty(reg, reg, 0, LanguageMode::SLOPPY)
.LoadNamedProperty(reg, 0, LanguageMode::STRICT)
.LoadNamedProperty(reg, 0, 0, LanguageMode::STRICT)
.LoadKeyedProperty(reg, 0, LanguageMode::STRICT)
.StoreNamedProperty(reg, reg, 0, LanguageMode::STRICT)
.StoreNamedProperty(reg, 0, 0, LanguageMode::STRICT)
.StoreKeyedProperty(reg, reg, 0, LanguageMode::STRICT);
// Emit closure operations.
......
......@@ -36,6 +36,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
Register reg_0(0);
Register reg_1(1);
Register reg_2 = Register::FromParameterIndex(2, builder.parameter_count());
int name_index = 21;
int feedback_slot = 97;
builder.LoadLiteral(heap_num_0)
......@@ -44,7 +45,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
.LoadLiteral(smi_0)
.LoadLiteral(smi_1)
.LoadAccumulatorWithRegister(reg_0)
.LoadNamedProperty(reg_1, feedback_slot, LanguageMode::SLOPPY)
.LoadNamedProperty(reg_1, name_index, feedback_slot, LanguageMode::SLOPPY)
.StoreAccumulatorInRegister(reg_2)
.CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
.Return();
......@@ -82,7 +83,8 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadICSloppy);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
CHECK_EQ(iterator.GetIndexOperand(1), feedback_slot);
CHECK_EQ(iterator.GetIndexOperand(1), name_index);
CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
CHECK(!iterator.done());
iterator.Advance();
......
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