0d1ffe30f8
For background and reasoning, see https://docs.google.com/document/d/1jvSEvXFHRkxg4JX-j6ho3nRqAF8vZI2Ai7RI8AY54gM/edit This is the first step towards pulling the DefineNamedOwn operation out of StoreIC. Summary of the renamed identifiers: Bytecodes: - StaNamedProperty -> SetNamedProperty: calls StoreIC and emitted for normal named property sets like obj.x = 1. - StaNamedOwnProperty -> DefineNamedOwnProperty: calls DefineNamedOwnIC (previously StoreOwnIC), and emitted for initialization of named properties in object literals and named public class fields. - StaKeyedProperty -> SetKeyedProperty: calls KeyedStoreIC and emitted for keyed property sets like obj[x] = 1. - StaKeyedPropertyAsDefine -> DefineKeyedOwnProperty: calls DefineKeyedOwnIC (previously KeyedDefineOwnIC) and emitted for initialization of private class fields and computed public class fields. - StaDataPropertyInLiteral -> DefineKeyedOwnPropertyInLiteral: calls DefineKeyedOwnPropertyInLiteral runtime function (previously DefineDataPropertyInLiteral) and emitted for initialization of keyed properties in object literals and static class initializers. (note that previously the StoreDataPropertyInLiteral runtime function name was taken by object spreads and array literal creation instead) - LdaKeyedProperty -> GetKeyedProperty, LdaNamedProperty -> GetNamedProperty, LdaNamedPropertyFromSuper -> GetNamedPropertyFromSuper: we drop the Sta prefix for the property store operations since the accumulator use is implicit and to make the wording more natural, for symmetry the Lda prefix for the property load operations is also dropped. opcodes: - (JS)StoreNamed -> (JS)SetNamedProperty: implements set semantics for named properties, compiled from SetNamedProperty (previously StaNamedProperty) and lowers to StoreIC or Runtime::kSetNamedProperty - (JS)StoreNamedOwn -> (JS)DefineNamedOwnProperty: implements define semantics for initializing named own properties in object literal and public class fields, compiled from DefineNamedOwnProperty (previously StaNamedOwnProperty) and lowers to DefineNamedOwnIC (previously StoreOwnIC) - (JS)StoreProperty -> (JS)SetKeyedProperty: implements set semantics for keyed properties, only compiled from SetKeyedProperty(previously StaKeyedProperty) and lowers to KeyedStoreIC - (JS)DefineProperty -> (JS)DefineKeyedOwnProperty: implements define semantics for initialization of private class fields and computed public class fields, compiled from DefineKeyedOwnProperty (previously StaKeyedPropertyAsDefine) and calls DefineKeyedOwnIC (previously KeyedDefineOwnIC). - (JS)StoreDataPropertyInLiteral -> (JS)DefineKeyedOwnPropertyInLiteral: implements define semantics for initialization of keyed properties in object literals and static class initializers, compiled from DefineKeyedOwnPropertyInLiteral (previously StaDataPropertyInLiteral) and calls the DefineKeyedOwnPropertyInLiteral runtime function (previously DefineDataPropertyInLiteral). Runtime: - DefineDataPropertyInLiteral -> DefineKeyedOwnPropertyInLiteral: following the bytecode/opcodes change, this is used by DefineKeyedOwnPropertyInLiteral (previously StaDataPropertyInLiteral) for object and class literal initialization. - StoreDataPropertyInLiteral -> DefineKeyedOwnPropertyInLiteral_Simple: it's just a simplified version of DefineDataPropertyInLiteral that does not update feedback or perform function name configuration. This is used by object spread and array literal creation. Since we are renaming DefineDataPropertyInLiteral to DefineKeyedOwnPropertyInLiteral, rename this simplified version with a `_Simple` suffix. We can consider merging it into DefineKeyedOwnPropertyInLiteral in the future. See https://docs.google.com/document/d/1jvSEvXFHRkxg4JX-j6ho3nRqAF8vZI2Ai7RI8AY54gM/edit?disco=AAAAQQIz6mU - Other changes following the bytecode/IR changes IC: - StoreOwn -> DefineNamedOwn: used for initialization of named properties in object literals and named public class fields. - StoreOwnIC -> DefineNamedOwnIC - StoreMode::kStoreOwn -> StoreMode::kDefineNamedOwn - StoreICMode::kStoreOwn -> StoreICMode::kDefineNamedOwn - IsStoreOwn() -> IsDefineNamedOwn() - DefineOwn -> DefineKeyedOwn: IsDefineOwnIC() was already just IsDefineKeyedOwnIC(), and IsAnyDefineOwn() includes both named and keyed defines so we don't need an extra generic predicate. - StoreMode::kDefineOwn -> StoreMode::kDefineKeyedOwn - StoreICMode::kDefineOwn -> StoreICMode::kDefineKeyedOwn - IsDefineOwn() -> IsDefineKeyedOwn() - IsDefineOwnIC() -> IsDefineKeyedOwnIC() - Removing IsKeyedDefineOwnIC() as its now a duplicate of IsDefineKeyedOwnIC() - KeyedDefineOwnIC -> DefineKeyedOwnIC, KeyedDefineOwnGenericGenerator() -> DefineKeyedOwnGenericGenerator: make the ordering of terms more consistent - IsAnyStoreOwn() -> IsAnyDefineOwn(): this includes the renamed and DefineNamedOwn and DefineKeyedOwn. Also is_any_store_own() is removed since it's just a duplicate of this. - IsKeyedStoreOwn() -> IsDefineNamedOwn(): it's unclear where the "keyed" part came from, but it's only used when DefineNamedOwnIC (previously StoreOwnIC) reuses KeyedStoreIC, so rename it accordingly Interpreter & compiler: - BytecodeArrayBuilder: following bytecode changes - StoreNamedProperty -> SetNamedProperty - StoreNamedOwnProperty -> DefineNamedOwnProperty - StoreKeyedProperty -> SetKeyedProperty - DefineKeyedProperty -> DefineKeyedOwnProperty - StoreDataPropertyInLiteral -> DefineKeyedOwnPropertyInLiteral - FeedbackSlotKind: - kDefineOwnKeyed -> kDefineKeyedOwn: make the ordering of terms more consistent - kStoreOwnNamed -> kDefineNamedOwn: following the IC change - kStoreNamed{Sloppy|Strict} -> kSetNamed{Sloppy|Strict}: only used in StoreIC for set semantics - kStoreKeyed{Sloppy|Strict} -> kSetKeyed{Sloppy|Strict}: only used in KeyedStoreIC for set semantics - kStoreDataPropertyInLiteral -> kDefineKeyedOwnPropertyInLiteral: following the IC change - BytecodeGraphBuilder - StoreMode::kNormal, kOwn -> NamedStoreMode::kSet, kDefineOwn: this is only used by BytecodeGraphBuilder::BuildNamedStore() to tell the difference between SetNamedProperty and DefineNamedOwnProperty operations. Not changed: - StoreIC and KeyedStoreIC currently contain mixed logic for both Set and Define operations, and the paths are controlled by feedback. The plan is to refactor the hierarchy like this: ``` - StoreIC - DefineNamedOwnIC - SetNamedIC (there could also be a NamedStoreIC if that's helpful) - KeyedStoreIC - SetKeyedIC - DefineKeyedOwnIC - DefineKeyedOwnICLiteral (could be merged into DefineKeyedOwnIC) - StoreInArrayLiteralIC - ... ``` StoreIC and KeyedStoreIC would then contain helpers shared by their subclasses, therefore it still makes sense to keep the word "Store" in their names since they would be generic base classes for both set and define operations. - The Lda and Sta prefixes of bytecodes not involving object properties (e.g. Ldar, Star, LdaZero) are kept, since this patch focuses on property operations, and distinction between Set and Define might be less relevant or nonexistent for bytecodes not involving object properties. We could consider rename some of them in future patches if that's helpful though. Bug: v8:12548 Change-Id: Ia36997b02f59a87da3247f20e0560a7eb13077f3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3481475 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Reviewed-by: Shu-yu Guo <syg@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Joyee Cheung <joyee@igalia.com> Cr-Commit-Position: refs/heads/main@{#79409}
271 lines
12 KiB
C++
271 lines
12 KiB
C++
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "src/interpreter/bytecode-array-iterator.h"
|
|
|
|
#include "src/init/v8.h"
|
|
#include "src/interpreter/bytecode-array-builder.h"
|
|
#include "src/numbers/hash-seed-inl.h"
|
|
#include "src/objects/objects-inl.h"
|
|
#include "src/objects/smi.h"
|
|
#include "test/unittests/interpreter/bytecode-utils.h"
|
|
#include "test/unittests/test-utils.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace interpreter {
|
|
|
|
class BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
|
|
public:
|
|
BytecodeArrayIteratorTest() = default;
|
|
~BytecodeArrayIteratorTest() override = default;
|
|
};
|
|
|
|
TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
|
|
// Use a builder to create an array with containing multiple bytecodes
|
|
// with 0, 1 and 2 operands.
|
|
FeedbackVectorSpec feedback_spec(zone());
|
|
BytecodeArrayBuilder builder(zone(), 3, 17, &feedback_spec);
|
|
AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
|
|
HashSeed(isolate()));
|
|
double heap_num_0 = 2.718;
|
|
double heap_num_1 = 2.0 * Smi::kMaxValue;
|
|
Smi zero = Smi::zero();
|
|
Smi smi_0 = Smi::FromInt(64);
|
|
Smi smi_1 = Smi::FromInt(-65536);
|
|
Register reg_0(0);
|
|
Register reg_16(16); // Something not eligible for short Star.
|
|
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
|
|
RegisterList triple = BytecodeUtils::NewRegisterList(0, 3);
|
|
Register param = Register::FromParameterIndex(2);
|
|
const AstRawString* name = ast_factory.GetOneByteString("abc");
|
|
uint32_t name_index = 2;
|
|
uint32_t load_feedback_slot = feedback_spec.AddLoadICSlot().ToInt();
|
|
uint32_t forin_feedback_slot = feedback_spec.AddForInSlot().ToInt();
|
|
uint32_t load_global_feedback_slot =
|
|
feedback_spec.AddLoadGlobalICSlot(TypeofMode::kNotInside).ToInt();
|
|
|
|
builder.LoadLiteral(heap_num_0)
|
|
.StoreAccumulatorInRegister(reg_0)
|
|
.LoadLiteral(heap_num_1)
|
|
.StoreAccumulatorInRegister(reg_0)
|
|
.LoadLiteral(zero)
|
|
.StoreAccumulatorInRegister(reg_0)
|
|
.LoadLiteral(smi_0)
|
|
.StoreAccumulatorInRegister(reg_0)
|
|
.LoadLiteral(smi_1)
|
|
.StoreAccumulatorInRegister(reg_16)
|
|
.LoadAccumulatorWithRegister(reg_0)
|
|
.BinaryOperation(Token::Value::ADD, reg_0, 2)
|
|
.StoreAccumulatorInRegister(reg_16)
|
|
.LoadNamedProperty(reg_16, name, load_feedback_slot)
|
|
.BinaryOperation(Token::Value::ADD, reg_0, 3)
|
|
.StoreAccumulatorInRegister(param)
|
|
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, pair)
|
|
.ForInPrepare(triple, forin_feedback_slot)
|
|
.CallRuntime(Runtime::kLoadIC_Miss, reg_0)
|
|
.Debugger()
|
|
.LoadGlobal(name, load_global_feedback_slot, TypeofMode::kNotInside)
|
|
.Return();
|
|
|
|
// Test iterator sees the expected output from the builder.
|
|
ast_factory.Internalize(isolate());
|
|
BytecodeArrayIterator iterator(builder.ToBytecodeArray(isolate()));
|
|
const int kPrefixByteSize = 1;
|
|
int offset = 0;
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetConstantForIndexOperand(0, isolate())->Number(),
|
|
heap_num_0);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar0);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar0, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetConstantForIndexOperand(0, isolate())->Number(),
|
|
heap_num_1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar0);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar0, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar0);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar0, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_0);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar0);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar0, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
|
|
EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) +
|
|
kPrefixByteSize;
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_16.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdar);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_16.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kGetNamedProperty);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_16.index());
|
|
EXPECT_EQ(iterator.GetIndexOperand(1), name_index);
|
|
EXPECT_EQ(iterator.GetIndexOperand(2), load_feedback_slot);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kGetNamedProperty, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), param.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(1).index(), param.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(1), 1);
|
|
EXPECT_EQ(iterator.GetRegisterCountOperand(2), 1u);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(3).index(), reg_0.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(3), 2);
|
|
CHECK(!iterator.done());
|
|
offset +=
|
|
Bytecodes::Size(Bytecode::kCallRuntimeForPair, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
|
|
EXPECT_EQ(iterator.GetRegisterOperandRange(0), 3);
|
|
EXPECT_EQ(iterator.GetIndexOperand(1), forin_feedback_slot);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kForInPrepare, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss);
|
|
EXPECT_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
|
|
EXPECT_EQ(iterator.GetRegisterCountOperand(2), 1u);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kCallRuntime, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
offset += Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
EXPECT_EQ(iterator.current_bytecode_size(), 3);
|
|
EXPECT_EQ(iterator.GetIndexOperand(1), load_global_feedback_slot);
|
|
offset += Bytecodes::Size(Bytecode::kLdaGlobal, OperandScale::kSingle);
|
|
iterator.Advance();
|
|
|
|
EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn);
|
|
EXPECT_EQ(iterator.current_offset(), offset);
|
|
EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
|
|
CHECK(!iterator.done());
|
|
iterator.Advance();
|
|
CHECK(iterator.done());
|
|
}
|
|
|
|
} // namespace interpreter
|
|
} // namespace internal
|
|
} // namespace v8
|