summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2018-12-04 08:20:37 +0100
committerMichaël Zasso <targos@protonmail.com>2018-12-06 15:23:33 +0100
commit9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3 (patch)
tree2b0c843168dafb939d8df8a15b2aa72b76dee51d /deps/v8/src/interpreter
parentb8fbe69db1292307adb2c2b2e0d5ef48c4ab2faf (diff)
downloadandroid-node-v8-9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3.tar.gz
android-node-v8-9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3.tar.bz2
android-node-v8-9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3.zip
deps: update V8 to 7.1.302.28
PR-URL: https://github.com/nodejs/node/pull/23423 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/interpreter')
-rw-r--r--deps/v8/src/interpreter/bytecode-array-builder.cc28
-rw-r--r--deps/v8/src/interpreter/bytecode-array-builder.h16
-rw-r--r--deps/v8/src/interpreter/bytecode-decoder.cc19
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.cc338
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.h13
-rw-r--r--deps/v8/src/interpreter/bytecode-operands.h13
-rw-r--r--deps/v8/src/interpreter/bytecode-register-allocator.h4
-rw-r--r--deps/v8/src/interpreter/bytecode-register-optimizer.h6
-rw-r--r--deps/v8/src/interpreter/bytecodes.cc8
-rw-r--r--deps/v8/src/interpreter/bytecodes.h21
-rw-r--r--deps/v8/src/interpreter/constant-array-builder.h2
-rw-r--r--deps/v8/src/interpreter/control-flow-builders.h16
-rw-r--r--deps/v8/src/interpreter/handler-table-builder.h2
-rw-r--r--deps/v8/src/interpreter/interpreter-assembler.cc36
-rw-r--r--deps/v8/src/interpreter/interpreter-generator.cc77
-rw-r--r--deps/v8/src/interpreter/interpreter-generator.h11
-rw-r--r--deps/v8/src/interpreter/interpreter-intrinsics-generator.cc33
-rw-r--r--deps/v8/src/interpreter/interpreter-intrinsics.h5
-rw-r--r--deps/v8/src/interpreter/interpreter.cc98
-rw-r--r--deps/v8/src/interpreter/interpreter.h9
-rw-r--r--deps/v8/src/interpreter/setup-interpreter-internal.cc102
-rw-r--r--deps/v8/src/interpreter/setup-interpreter.h33
22 files changed, 455 insertions, 435 deletions
diff --git a/deps/v8/src/interpreter/bytecode-array-builder.cc b/deps/v8/src/interpreter/bytecode-array-builder.cc
index 33731599c8..a7c95aae7b 100644
--- a/deps/v8/src/interpreter/bytecode-array-builder.cc
+++ b/deps/v8/src/interpreter/bytecode-array-builder.cc
@@ -23,7 +23,7 @@ class RegisterTransferWriter final
public NON_EXPORTED_BASE(ZoneObject) {
public:
RegisterTransferWriter(BytecodeArrayBuilder* builder) : builder_(builder) {}
- ~RegisterTransferWriter() override {}
+ ~RegisterTransferWriter() override = default;
void EmitLdar(Register input) override { builder_->OutputLdarRaw(input); }
@@ -797,6 +797,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
return *this;
}
+BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
+ Register object, const AstRawString* name) {
+ size_t name_index = GetConstantPoolEntry(name);
+ OutputLdaNamedPropertyNoFeedback(object, name_index);
+ return *this;
+}
+
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
Register object, int feedback_slot) {
OutputLdaKeyedProperty(object, feedback_slot);
@@ -847,6 +854,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
return StoreNamedProperty(object, name_index, feedback_slot, language_mode);
}
+BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedPropertyNoFeedback(
+ Register object, const AstRawString* name, LanguageMode language_mode) {
+ size_t name_index = GetConstantPoolEntry(name);
+ OutputStaNamedPropertyNoFeedback(object, name_index,
+ static_cast<uint8_t>(language_mode));
+ return *this;
+}
+
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedOwnProperty(
Register object, const AstRawString* name, int feedback_slot) {
size_t name_index = GetConstantPoolEntry(name);
@@ -973,6 +988,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
return *this;
}
+BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayFromIterable() {
+ OutputCreateArrayFromIterable();
+ return *this;
+}
+
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
size_t constant_properties_entry, int literal_index, int flags,
Register output) {
@@ -1375,6 +1395,12 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable,
return *this;
}
+BytecodeArrayBuilder& BytecodeArrayBuilder::CallNoFeedback(Register callable,
+ RegisterList args) {
+ OutputCallNoFeedback(callable, args, args.register_count());
+ return *this;
+}
+
BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
RegisterList args,
int feedback_slot) {
diff --git a/deps/v8/src/interpreter/bytecode-array-builder.h b/deps/v8/src/interpreter/bytecode-array-builder.h
index 3feda90495..bf5909d8e4 100644
--- a/deps/v8/src/interpreter/bytecode-array-builder.h
+++ b/deps/v8/src/interpreter/bytecode-array-builder.h
@@ -120,6 +120,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& LoadNamedProperty(Register object,
const AstRawString* name,
int feedback_slot);
+ // Named load property without feedback
+ BytecodeArrayBuilder& LoadNamedPropertyNoFeedback(Register object,
+ const AstRawString* name);
+
// Keyed load property. The key should be in the accumulator.
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
// Named load property of the @@iterator symbol.
@@ -145,6 +149,12 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
const AstRawString* name,
int feedback_slot,
LanguageMode language_mode);
+
+ // Store a property named by a property name without feedback slot. The value
+ // to be stored should be in the accumulator.
+ BytecodeArrayBuilder& StoreNamedPropertyNoFeedback(
+ Register object, const AstRawString* name, LanguageMode language_mode);
+
// Store a property named by a constant from the constant pool. The value to
// be stored should be in the accumulator.
BytecodeArrayBuilder& StoreNamedProperty(Register object,
@@ -234,6 +244,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
int literal_index, int flags);
BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
+ BytecodeArrayBuilder& CreateArrayFromIterable();
BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
int literal_index, int flags,
Register output);
@@ -276,6 +287,11 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args,
int feedback_slot);
+ // Call a JS function with an any receiver, possibly (but not necessarily)
+ // undefined. The JSFunction or Callable to be called should be in |callable|.
+ // The arguments should be in |args|, with the receiver in |args[0]|.
+ BytecodeArrayBuilder& CallNoFeedback(Register callable, RegisterList args);
+
// Tail call into a JS function. The JSFunction or Callable to be called
// should be in |callable|. The arguments should be in |args|, with the
// receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in
diff --git a/deps/v8/src/interpreter/bytecode-decoder.cc b/deps/v8/src/interpreter/bytecode-decoder.cc
index e684eb410b..fa0ff9e4a8 100644
--- a/deps/v8/src/interpreter/bytecode-decoder.cc
+++ b/deps/v8/src/interpreter/bytecode-decoder.cc
@@ -71,18 +71,8 @@ uint32_t BytecodeDecoder::DecodeUnsignedOperand(Address operand_start,
namespace {
-const char* NameForRuntimeId(uint32_t idx) {
- switch (idx) {
-#define CASE(name, nargs, ressize) \
- case Runtime::k##name: \
- return #name; \
- case Runtime::kInline##name: \
- return "_" #name;
- FOR_EACH_INTRINSIC(CASE)
-#undef CASE
- default:
- UNREACHABLE();
- }
+const char* NameForRuntimeId(Runtime::FunctionId idx) {
+ return Runtime::FunctionForId(idx)->name;
}
const char* NameForNativeContextIndex(uint32_t idx) {
@@ -160,8 +150,9 @@ std::ostream& BytecodeDecoder::Decode(std::ostream& os,
break;
}
case interpreter::OperandType::kRuntimeId:
- os << "[" << NameForRuntimeId(DecodeUnsignedOperand(
- operand_start, op_type, operand_scale))
+ os << "["
+ << NameForRuntimeId(static_cast<Runtime::FunctionId>(
+ DecodeUnsignedOperand(operand_start, op_type, operand_scale)))
<< "]";
break;
case interpreter::OperandType::kImm:
diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc
index 11a19443e1..b00d3773cd 100644
--- a/deps/v8/src/interpreter/bytecode-generator.cc
+++ b/deps/v8/src/interpreter/bytecode-generator.cc
@@ -29,7 +29,7 @@ namespace interpreter {
// Scoped class tracking context objects created by the visitor. Represents
// mutations of the context chain within the function body, allowing pushing and
// popping of the current {context_register} during visitation.
-class BytecodeGenerator::ContextScope BASE_EMBEDDED {
+class BytecodeGenerator::ContextScope {
public:
ContextScope(BytecodeGenerator* generator, Scope* scope)
: generator_(generator),
@@ -94,7 +94,7 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED {
// Scoped class for tracking control statements entered by the
// visitor. The pattern derives AstGraphBuilder::ControlScope.
-class BytecodeGenerator::ControlScope BASE_EMBEDDED {
+class BytecodeGenerator::ControlScope {
public:
explicit ControlScope(BytecodeGenerator* generator)
: generator_(generator), outer_(generator->execution_control()),
@@ -402,7 +402,7 @@ class BytecodeGenerator::ControlScopeForIteration final
loop_builder_(loop_builder) {
generator->loop_depth_++;
}
- ~ControlScopeForIteration() { generator()->loop_depth_--; }
+ ~ControlScopeForIteration() override { generator()->loop_depth_--; }
protected:
bool Execute(Command command, Statement* statement,
@@ -908,7 +908,7 @@ BytecodeGenerator::BytecodeGenerator(
execution_context_(nullptr),
execution_result_(nullptr),
incoming_new_target_or_generator_(),
- dummy_feedback_slot_(),
+ dummy_feedback_slot_(feedback_spec(), FeedbackSlotKind::kCompareOp),
generator_jump_table_(nullptr),
suspend_count_(0),
loop_depth_(0),
@@ -1820,7 +1820,11 @@ bool BytecodeGenerator::ShouldOptimizeAsOneShot() const {
if (loop_depth_ > 0) return false;
- return info()->literal()->is_top_level() || info()->literal()->is_iife();
+ // A non-top-level iife is likely to be executed multiple times and so
+ // shouldn`t be optimized as one-shot.
+ bool is_toplevel_iife = info()->literal()->is_iife() &&
+ current_scope()->outer_scope()->is_script_scope();
+ return info()->literal()->is_toplevel() || is_toplevel_iife;
}
void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr) {
@@ -1859,6 +1863,7 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr) {
DCHECK_NE(property->kind(), ClassLiteral::Property::PRIVATE_FIELD);
Register key = register_allocator()->GrowRegisterList(&args);
+ builder()->SetExpressionAsStatementPosition(property->key());
BuildLoadPropertyKey(property, key);
if (property->is_static()) {
// The static prototype property is read only. We handle the non
@@ -1968,13 +1973,13 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
}
void BytecodeGenerator::VisitInitializeClassFieldsStatement(
- InitializeClassFieldsStatement* expr) {
+ InitializeClassFieldsStatement* stmt) {
RegisterList args = register_allocator()->NewRegisterList(3);
Register constructor = args[0], key = args[1], value = args[2];
builder()->MoveRegister(builder()->Receiver(), constructor);
- for (int i = 0; i < expr->fields()->length(); i++) {
- ClassLiteral::Property* property = expr->fields()->at(i);
+ for (int i = 0; i < stmt->fields()->length(); i++) {
+ ClassLiteral::Property* property = stmt->fields()->at(i);
if (property->is_computed_name()) {
DCHECK_EQ(property->kind(), ClassLiteral::Property::PUBLIC_FIELD);
@@ -1993,6 +1998,7 @@ void BytecodeGenerator::VisitInitializeClassFieldsStatement(
BuildLoadPropertyKey(property, key);
}
+ builder()->SetExpressionAsStatementPosition(property->value());
VisitForRegisterValue(property->value(), value);
VisitSetHomeObject(value, constructor, property);
@@ -2231,7 +2237,7 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
builder()
->LoadLiteral(Smi::FromEnum(LanguageMode::kSloppy))
.StoreAccumulatorInRegister(args[3])
- .CallRuntime(Runtime::kSetProperty, args);
+ .CallRuntime(Runtime::kSetKeyedProperty, args);
Register value = args[2];
VisitSetHomeObject(value, literal, property);
}
@@ -2364,116 +2370,6 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
builder()->LoadAccumulatorWithRegister(literal);
}
-void BytecodeGenerator::BuildArrayLiteralElementsInsertion(
- Register array, int first_spread_index, ZonePtrList<Expression>* elements,
- bool skip_constants) {
- DCHECK_LT(first_spread_index, elements->length());
-
- Register index = register_allocator()->NewRegister();
- int array_index = 0;
-
- ZonePtrList<Expression>::iterator iter = elements->begin();
- ZonePtrList<Expression>::iterator first_spread_or_end =
- first_spread_index >= 0 ? elements->begin() + first_spread_index
- : elements->end();
-
- // Evaluate subexpressions and store them into the array.
- FeedbackSlot keyed_store_slot;
- for (; iter != first_spread_or_end; ++iter, array_index++) {
- Expression* subexpr = *iter;
- DCHECK(!subexpr->IsSpread());
- if (skip_constants && subexpr->IsCompileTimeValue()) continue;
- if (keyed_store_slot.IsInvalid()) {
- keyed_store_slot = feedback_spec()->AddKeyedStoreICSlot(language_mode());
- }
- builder()
- ->LoadLiteral(Smi::FromInt(array_index))
- .StoreAccumulatorInRegister(index);
- VisitForAccumulatorValue(subexpr);
- builder()->StoreKeyedProperty(
- array, index, feedback_index(keyed_store_slot), language_mode());
- }
- if (iter != elements->end()) {
- builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
-
- // Handle the first spread element and everything that follows.
- FeedbackSlot element_slot = feedback_spec()->AddStoreInArrayLiteralICSlot();
- FeedbackSlot index_slot = feedback_spec()->AddBinaryOpICSlot();
- // TODO(neis): Only create length_slot when there are holes.
- FeedbackSlot length_slot =
- feedback_spec()->AddStoreICSlot(LanguageMode::kStrict);
- for (; iter != elements->end(); ++iter) {
- Expression* subexpr = *iter;
- if (subexpr->IsSpread()) {
- BuildArrayLiteralSpread(subexpr->AsSpread(), array, index, index_slot,
- element_slot);
- } else if (!subexpr->IsTheHoleLiteral()) {
- // literal[index++] = subexpr
- VisitForAccumulatorValue(subexpr);
- builder()
- ->StoreInArrayLiteral(array, index, feedback_index(element_slot))
- .LoadAccumulatorWithRegister(index)
- .UnaryOperation(Token::INC, feedback_index(index_slot))
- .StoreAccumulatorInRegister(index);
- } else {
- // literal.length = ++index
- auto length = ast_string_constants()->length_string();
- builder()
- ->LoadAccumulatorWithRegister(index)
- .UnaryOperation(Token::INC, feedback_index(index_slot))
- .StoreAccumulatorInRegister(index)
- .StoreNamedProperty(array, length, feedback_index(length_slot),
- LanguageMode::kStrict);
- }
- }
- }
- builder()->LoadAccumulatorWithRegister(array);
-}
-
-void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
- expr->InitDepthAndFlags();
- uint8_t flags = CreateArrayLiteralFlags::Encode(
- expr->IsFastCloningSupported(), expr->ComputeFlags());
-
- bool is_empty = expr->is_empty();
- bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
- size_t entry;
- if (is_empty && optimize_as_one_shot) {
- entry = builder()->EmptyArrayBoilerplateDescriptionConstantPoolEntry();
- } else if (!is_empty) {
- entry = builder()->AllocateDeferredConstantPoolEntry();
- array_literals_.push_back(std::make_pair(expr, entry));
- }
-
- if (optimize_as_one_shot) {
- // Create array literal without any allocation sites
- RegisterAllocationScope register_scope(this);
- RegisterList args = register_allocator()->NewRegisterList(2);
- builder()
- ->LoadConstantPoolEntry(entry)
- .StoreAccumulatorInRegister(args[0])
- .LoadLiteral(Smi::FromInt(flags))
- .StoreAccumulatorInRegister(args[1])
- .CallRuntime(Runtime::kCreateArrayLiteralWithoutAllocationSite, args);
- } else if (is_empty) {
- // Empty array literal fast-path.
- int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
- DCHECK(expr->IsFastCloningSupported());
- builder()->CreateEmptyArrayLiteral(literal_index);
- return;
- } else {
- // Deep-copy the literal boilerplate
- int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
- builder()->CreateArrayLiteral(entry, literal_index, flags);
- }
-
- Register literal = register_allocator()->NewRegister();
- builder()->StoreAccumulatorInRegister(literal);
- // Insert all elements except the constant ones, since they are already there.
- BuildArrayLiteralElementsInsertion(literal, expr->first_spread_index(),
- expr->values(), true);
-}
-
void BytecodeGenerator::BuildArrayLiteralSpread(Spread* spread, Register array,
Register index,
FeedbackSlot index_slot,
@@ -2513,6 +2409,154 @@ void BytecodeGenerator::BuildArrayLiteralSpread(Spread* spread, Register array,
loop_builder.JumpToHeader(loop_depth_);
}
+void BytecodeGenerator::BuildCreateArrayLiteral(
+ ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
+ RegisterAllocationScope register_scope(this);
+ Register index = register_allocator()->NewRegister();
+ Register array = register_allocator()->NewRegister();
+ SharedFeedbackSlot element_slot(feedback_spec(),
+ FeedbackSlotKind::kStoreInArrayLiteral);
+ ZonePtrList<Expression>::iterator current = elements->begin();
+ ZonePtrList<Expression>::iterator end = elements->end();
+ bool is_empty = elements->is_empty();
+
+ if (!is_empty && (*current)->IsSpread()) {
+ // If we have a leading spread, use CreateArrayFromIterable to create
+ // an array from it and then add the remaining components to that array.
+ VisitForAccumulatorValue(*current);
+ builder()->CreateArrayFromIterable().StoreAccumulatorInRegister(array);
+
+ if (++current != end) {
+ // If there are remaning elements, prepare the index register that is
+ // used for adding those elements. The next index is the length of the
+ // newly created array.
+ auto length = ast_string_constants()->length_string();
+ int length_load_slot = feedback_index(feedback_spec()->AddLoadICSlot());
+ builder()
+ ->LoadNamedProperty(array, length, length_load_slot)
+ .StoreAccumulatorInRegister(index);
+ }
+ } else if (expr != nullptr) {
+ // There are some elements before the first (if any) spread, and we can
+ // use a boilerplate when creating the initial array from those elements.
+
+ // First, allocate a constant pool entry for the boilerplate that will
+ // be created during finalization, and will contain all the constant
+ // elements before the first spread. This also handle the empty array case
+ // and one-shot optimization.
+ uint8_t flags = CreateArrayLiteralFlags::Encode(
+ expr->IsFastCloningSupported(), expr->ComputeFlags());
+ bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
+ size_t entry;
+ if (is_empty && optimize_as_one_shot) {
+ entry = builder()->EmptyArrayBoilerplateDescriptionConstantPoolEntry();
+ } else if (!is_empty) {
+ entry = builder()->AllocateDeferredConstantPoolEntry();
+ array_literals_.push_back(std::make_pair(expr, entry));
+ }
+
+ if (optimize_as_one_shot) {
+ RegisterList args = register_allocator()->NewRegisterList(2);
+ builder()
+ ->LoadConstantPoolEntry(entry)
+ .StoreAccumulatorInRegister(args[0])
+ .LoadLiteral(Smi::FromInt(flags))
+ .StoreAccumulatorInRegister(args[1])
+ .CallRuntime(Runtime::kCreateArrayLiteralWithoutAllocationSite, args);
+ } else if (is_empty) {
+ // Empty array literal fast-path.
+ int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
+ DCHECK(expr->IsFastCloningSupported());
+ builder()->CreateEmptyArrayLiteral(literal_index);
+ } else {
+ // Create array literal from boilerplate.
+ int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
+ builder()->CreateArrayLiteral(entry, literal_index, flags);
+ }
+ builder()->StoreAccumulatorInRegister(array);
+
+ // Insert the missing non-constant elements, up until the first spread
+ // index, into the initial array (the remaining elements will be inserted
+ // below).
+ DCHECK_EQ(current, elements->begin());
+ ZonePtrList<Expression>::iterator first_spread_or_end =
+ expr->first_spread_index() >= 0 ? current + expr->first_spread_index()
+ : end;
+ int array_index = 0;
+ for (; current != first_spread_or_end; ++current, array_index++) {
+ Expression* subexpr = *current;
+ DCHECK(!subexpr->IsSpread());
+ // Skip the constants.
+ if (subexpr->IsCompileTimeValue()) continue;
+
+ builder()
+ ->LoadLiteral(Smi::FromInt(array_index))
+ .StoreAccumulatorInRegister(index);
+ VisitForAccumulatorValue(subexpr);
+ builder()->StoreInArrayLiteral(array, index,
+ feedback_index(element_slot.Get()));
+ }
+
+ if (current != end) {
+ // If there are remaining elements, prepare the index register
+ // to store the next element, which comes from the first spread.
+ builder()->LoadLiteral(array_index).StoreAccumulatorInRegister(index);
+ }
+ } else {
+ // In other cases, we prepare an empty array to be filled in below.
+ DCHECK(!elements->is_empty());
+ int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
+ builder()
+ ->CreateEmptyArrayLiteral(literal_index)
+ .StoreAccumulatorInRegister(array);
+ // Prepare the index for the first element.
+ builder()->LoadLiteral(Smi::FromInt(0)).StoreAccumulatorInRegister(index);
+ }
+
+ // Now build insertions for the remaining elements from current to end.
+ SharedFeedbackSlot index_slot(feedback_spec(), FeedbackSlotKind::kBinaryOp);
+ SharedFeedbackSlot length_slot(
+ feedback_spec(), feedback_spec()->GetStoreICSlot(LanguageMode::kStrict));
+ for (; current != end; ++current) {
+ Expression* subexpr = *current;
+ if (subexpr->IsSpread()) {
+ FeedbackSlot real_index_slot = index_slot.Get();
+ BuildArrayLiteralSpread(subexpr->AsSpread(), array, index,
+ real_index_slot, element_slot.Get());
+ } else if (!subexpr->IsTheHoleLiteral()) {
+ // literal[index++] = subexpr
+ VisitForAccumulatorValue(subexpr);
+ builder()
+ ->StoreInArrayLiteral(array, index,
+ feedback_index(element_slot.Get()))
+ .LoadAccumulatorWithRegister(index);
+ // Only increase the index if we are not the last element.
+ if (current + 1 != end) {
+ builder()
+ ->UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
+ .StoreAccumulatorInRegister(index);
+ }
+ } else {
+ // literal.length = ++index
+ // length_slot is only used when there are holes.
+ auto length = ast_string_constants()->length_string();
+ builder()
+ ->LoadAccumulatorWithRegister(index)
+ .UnaryOperation(Token::INC, feedback_index(index_slot.Get()))
+ .StoreAccumulatorInRegister(index)
+ .StoreNamedProperty(array, length, feedback_index(length_slot.Get()),
+ LanguageMode::kStrict);
+ }
+ }
+
+ builder()->LoadAccumulatorWithRegister(array);
+}
+
+void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
+ expr->InitDepthAndFlags();
+ BuildCreateArrayLiteral(expr->values(), expr);
+}
+
void BytecodeGenerator::VisitStoreInArrayLiteral(StoreInArrayLiteral* expr) {
builder()->SetExpressionAsStatementPosition(expr);
RegisterAllocationScope register_scope(this);
@@ -2824,13 +2868,7 @@ void BytecodeGenerator::BuildLoadNamedProperty(Property* property,
Register object,
const AstRawString* name) {
if (ShouldOptimizeAsOneShot()) {
- RegisterList args = register_allocator()->NewRegisterList(2);
- size_t name_index = builder()->GetConstantPoolEntry(name);
- builder()
- ->MoveRegister(object, args[0])
- .LoadConstantPoolEntry(name_index)
- .StoreAccumulatorInRegister(args[1])
- .CallRuntime(Runtime::kInlineGetProperty, args);
+ builder()->LoadNamedPropertyNoFeedback(object, name);
} else {
FeedbackSlot slot = GetCachedLoadICSlot(property->obj(), name);
builder()->LoadNamedProperty(object, name, feedback_index(slot));
@@ -2847,16 +2885,7 @@ void BytecodeGenerator::BuildStoreNamedProperty(Property* property,
}
if (ShouldOptimizeAsOneShot()) {
- RegisterList args = register_allocator()->NewRegisterList(4);
- size_t name_index = builder()->GetConstantPoolEntry(name);
- builder()
- ->MoveRegister(object, args[0])
- .StoreAccumulatorInRegister(args[2])
- .LoadConstantPoolEntry(name_index)
- .StoreAccumulatorInRegister(args[1])
- .LoadLiteral(Smi::FromEnum(language_mode()))
- .StoreAccumulatorInRegister(args[3])
- .CallRuntime(Runtime::kSetProperty, args);
+ builder()->StoreNamedPropertyNoFeedback(object, name, language_mode());
} else {
FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name);
builder()->StoreNamedProperty(object, name, feedback_index(slot),
@@ -3555,6 +3584,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// When a call contains a spread, a Call AST node is only created if there is
// exactly one spread, and it is the last argument.
bool is_spread_call = expr->only_last_arg_is_spread();
+ bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
// TODO(petermarshall): We have a lot of call bytecodes that are very similar,
// see if we can reduce the number by adding a separate argument which
@@ -3579,7 +3609,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
}
case Call::GLOBAL_CALL: {
// Receiver is undefined for global calls.
- if (!is_spread_call) {
+ if (!is_spread_call && !optimize_as_one_shot) {
implicit_undefined_receiver = true;
} else {
// TODO(leszeks): There's no special bytecode for tail calls or spread
@@ -3615,7 +3645,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
}
case Call::OTHER_CALL: {
// Receiver is undefined for other calls.
- if (!is_spread_call) {
+ if (!is_spread_call && !optimize_as_one_shot) {
implicit_undefined_receiver = true;
} else {
// TODO(leszeks): There's no special bytecode for tail calls or spread
@@ -3679,20 +3709,25 @@ void BytecodeGenerator::VisitCall(Call* expr) {
builder()->SetExpressionPosition(expr);
- int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
-
if (is_spread_call) {
DCHECK(!implicit_undefined_receiver);
- builder()->CallWithSpread(callee, args, feedback_slot_index);
+ builder()->CallWithSpread(callee, args,
+ feedback_index(feedback_spec()->AddCallICSlot()));
+ } else if (optimize_as_one_shot) {
+ DCHECK(!implicit_undefined_receiver);
+ builder()->CallNoFeedback(callee, args);
} else if (call_type == Call::NAMED_PROPERTY_CALL ||
call_type == Call::KEYED_PROPERTY_CALL ||
call_type == Call::RESOLVED_PROPERTY_CALL) {
DCHECK(!implicit_undefined_receiver);
- builder()->CallProperty(callee, args, feedback_slot_index);
+ builder()->CallProperty(callee, args,
+ feedback_index(feedback_spec()->AddCallICSlot()));
} else if (implicit_undefined_receiver) {
- builder()->CallUndefinedReceiver(callee, args, feedback_slot_index);
+ builder()->CallUndefinedReceiver(
+ callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
} else {
- builder()->CallAnyReceiver(callee, args, feedback_slot_index);
+ builder()->CallAnyReceiver(
+ callee, args, feedback_index(feedback_spec()->AddCallICSlot()));
}
}
@@ -3722,17 +3757,12 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// mechanism for spreads in array literals.
// First generate the array containing all arguments.
- Register array = register_allocator()->NewRegister();
- int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
- builder()
- ->CreateEmptyArrayLiteral(literal_index)
- .StoreAccumulatorInRegister(array);
- BuildArrayLiteralElementsInsertion(array, first_spread_index, args, false);
+ BuildCreateArrayLiteral(args, nullptr);
// Now pass that array to %reflect_construct.
RegisterList construct_args = register_allocator()->NewRegisterList(3);
+ builder()->StoreAccumulatorInRegister(construct_args[1]);
builder()->MoveRegister(constructor, construct_args[0]);
- builder()->MoveRegister(array, construct_args[1]);
VisitForRegisterValue(super->new_target_var(), construct_args[2]);
builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
} else {
@@ -5175,11 +5205,7 @@ FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot(
}
FeedbackSlot BytecodeGenerator::GetDummyCompareICSlot() {
- if (!dummy_feedback_slot_.IsInvalid()) {
- return dummy_feedback_slot_;
- }
- dummy_feedback_slot_ = feedback_spec()->AddCompareICSlot();
- return dummy_feedback_slot_;
+ return dummy_feedback_slot_.Get();
}
Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() {
diff --git a/deps/v8/src/interpreter/bytecode-generator.h b/deps/v8/src/interpreter/bytecode-generator.h
index 47f1f83e12..3150245b0b 100644
--- a/deps/v8/src/interpreter/bytecode-generator.h
+++ b/deps/v8/src/interpreter/bytecode-generator.h
@@ -6,6 +6,7 @@
#define V8_INTERPRETER_BYTECODE_GENERATOR_H_
#include "src/ast/ast.h"
+#include "src/feedback-vector.h"
#include "src/interpreter/bytecode-array-builder.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register.h"
@@ -182,11 +183,11 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildArrayLiteralSpread(Spread* spread, Register array, Register index,
FeedbackSlot index_slot,
FeedbackSlot element_slot);
- void BuildArrayLiteralElementsInsertion(Register array,
- int first_spread_index,
- ZonePtrList<Expression>* elements,
- bool skip_constants);
-
+ // Create Array literals. |expr| can be nullptr, but if provided,
+ // a boilerplate will be used to create an initial array for elements
+ // before the first spread.
+ void BuildCreateArrayLiteral(ZonePtrList<Expression>* elements,
+ ArrayLiteral* expr);
void BuildCreateObjectLiteral(Register literal, uint8_t flags, size_t entry);
void AllocateTopLevelRegisters();
void VisitArgumentsObject(Variable* variable);
@@ -373,7 +374,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
// Dummy feedback slot for compare operations, where we don't care about
// feedback
- FeedbackSlot dummy_feedback_slot_;
+ SharedFeedbackSlot dummy_feedback_slot_;
BytecodeJumpTable* generator_jump_table_;
int suspend_count_;
diff --git a/deps/v8/src/interpreter/bytecode-operands.h b/deps/v8/src/interpreter/bytecode-operands.h
index 04d1e35821..a2730cb64c 100644
--- a/deps/v8/src/interpreter/bytecode-operands.h
+++ b/deps/v8/src/interpreter/bytecode-operands.h
@@ -145,6 +145,19 @@ class BytecodeOperands : public AllStatic {
0 OPERAND_SCALE_LIST(OPERAND_SCALE_COUNT);
#undef OPERAND_SCALE_COUNT
+ static int OperandScaleAsIndex(OperandScale operand_scale) {
+ switch (operand_scale) {
+ case OperandScale::kSingle:
+ return 0;
+ case OperandScale::kDouble:
+ return 1;
+ case OperandScale::kQuadruple:
+ return 2;
+ default:
+ UNREACHABLE();
+ }
+ }
+
// Returns true if |accumulator_use| reads the accumulator.
static constexpr bool ReadsAccumulator(AccumulatorUse accumulator_use) {
return accumulator_use == AccumulatorUse::kRead ||
diff --git a/deps/v8/src/interpreter/bytecode-register-allocator.h b/deps/v8/src/interpreter/bytecode-register-allocator.h
index 8509bd43e0..b270e3d38b 100644
--- a/deps/v8/src/interpreter/bytecode-register-allocator.h
+++ b/deps/v8/src/interpreter/bytecode-register-allocator.h
@@ -19,7 +19,7 @@ class BytecodeRegisterAllocator final {
// Enables observation of register allocation and free events.
class Observer {
public:
- virtual ~Observer() {}
+ virtual ~Observer() = default;
virtual void RegisterAllocateEvent(Register reg) = 0;
virtual void RegisterListAllocateEvent(RegisterList reg_list) = 0;
virtual void RegisterListFreeEvent(RegisterList reg_list) = 0;
@@ -29,7 +29,7 @@ class BytecodeRegisterAllocator final {
: next_register_index_(start_index),
max_register_count_(start_index),
observer_(nullptr) {}
- ~BytecodeRegisterAllocator() {}
+ ~BytecodeRegisterAllocator() = default;
// Returns a new register.
Register NewRegister() {
diff --git a/deps/v8/src/interpreter/bytecode-register-optimizer.h b/deps/v8/src/interpreter/bytecode-register-optimizer.h
index 11794274b9..7ba7d3b602 100644
--- a/deps/v8/src/interpreter/bytecode-register-optimizer.h
+++ b/deps/v8/src/interpreter/bytecode-register-optimizer.h
@@ -23,8 +23,8 @@ class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final
public:
class BytecodeWriter {
public:
- BytecodeWriter() {}
- virtual ~BytecodeWriter() {}
+ BytecodeWriter() = default;
+ virtual ~BytecodeWriter() = default;
// Called to emit a register transfer bytecode.
virtual void EmitLdar(Register input) = 0;
@@ -39,7 +39,7 @@ class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final
BytecodeRegisterAllocator* register_allocator,
int fixed_registers_count, int parameter_count,
BytecodeWriter* bytecode_writer);
- virtual ~BytecodeRegisterOptimizer() {}
+ ~BytecodeRegisterOptimizer() override = default;
// Perform explicit register transfer operations.
void DoLdar(Register input) {
diff --git a/deps/v8/src/interpreter/bytecodes.cc b/deps/v8/src/interpreter/bytecodes.cc
index 88cdae6ce5..60f30ee1d9 100644
--- a/deps/v8/src/interpreter/bytecodes.cc
+++ b/deps/v8/src/interpreter/bytecodes.cc
@@ -107,14 +107,13 @@ const char* Bytecodes::ToString(Bytecode bytecode) {
}
// static
-std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) {
- static const char kSeparator = '.';
-
+std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale,
+ const char* separator) {
std::string value(ToString(bytecode));
if (operand_scale > OperandScale::kSingle) {
Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
std::string suffix = ToString(prefix_bytecode);
- return value.append(1, kSeparator).append(suffix);
+ return value.append(separator).append(suffix);
} else {
return value;
}
@@ -284,6 +283,7 @@ bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
case Bytecode::kDec:
case Bytecode::kTypeOf:
case Bytecode::kCallAnyReceiver:
+ case Bytecode::kCallNoFeedback:
case Bytecode::kCallProperty:
case Bytecode::kCallProperty0:
case Bytecode::kCallProperty1:
diff --git a/deps/v8/src/interpreter/bytecodes.h b/deps/v8/src/interpreter/bytecodes.h
index 0e543877f7..39f61eb9bd 100644
--- a/deps/v8/src/interpreter/bytecodes.h
+++ b/deps/v8/src/interpreter/bytecodes.h
@@ -98,6 +98,8 @@ namespace interpreter {
/* Property loads (LoadIC) operations */ \
V(LdaNamedProperty, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
+ V(LdaNamedPropertyNoFeedback, AccumulatorUse::kWrite, OperandType::kReg, \
+ OperandType::kIdx) \
V(LdaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
\
@@ -110,6 +112,8 @@ namespace interpreter {
/* Propery stores (StoreIC) operations */ \
V(StaNamedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
+ V(StaNamedPropertyNoFeedback, AccumulatorUse::kReadWrite, OperandType::kReg, \
+ OperandType::kIdx, OperandType::kFlag8) \
V(StaNamedOwnProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx) \
V(StaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
@@ -194,6 +198,8 @@ namespace interpreter {
OperandType::kReg, OperandType::kIdx) \
V(CallUndefinedReceiver2, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kReg, OperandType::kReg, OperandType::kIdx) \
+ V(CallNoFeedback, AccumulatorUse::kWrite, OperandType::kReg, \
+ OperandType::kRegList, OperandType::kRegCount) \
V(CallWithSpread, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \
V(CallRuntime, AccumulatorUse::kWrite, OperandType::kRuntimeId, \
@@ -247,6 +253,7 @@ namespace interpreter {
OperandType::kIdx, OperandType::kFlag8) \
V(CreateArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx, \
OperandType::kIdx, OperandType::kFlag8) \
+ V(CreateArrayFromIterable, AccumulatorUse::kReadWrite) \
V(CreateEmptyArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx) \
V(CreateObjectLiteral, AccumulatorUse::kNone, OperandType::kIdx, \
OperandType::kIdx, OperandType::kFlag8, OperandType::kRegOut) \
@@ -468,8 +475,10 @@ class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
// Returns string representation of |bytecode|.
static const char* ToString(Bytecode bytecode);
- // Returns string representation of |bytecode|.
- static std::string ToString(Bytecode bytecode, OperandScale operand_scale);
+ // Returns string representation of |bytecode| combined with |operand_scale|
+ // using the optionally provided |separator|.
+ static std::string ToString(Bytecode bytecode, OperandScale operand_scale,
+ const char* separator = ".");
// Returns byte value of bytecode.
static uint8_t ToByte(Bytecode bytecode) {
@@ -664,6 +673,7 @@ class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
bytecode == Bytecode::kCallUndefinedReceiver0 ||
bytecode == Bytecode::kCallUndefinedReceiver1 ||
bytecode == Bytecode::kCallUndefinedReceiver2 ||
+ bytecode == Bytecode::kCallNoFeedback ||
bytecode == Bytecode::kConstruct ||
bytecode == Bytecode::kCallWithSpread ||
bytecode == Bytecode::kConstructWithSpread ||
@@ -684,12 +694,6 @@ class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
bytecode == Bytecode::kDebugBreakWide;
}
- // Returns true if the bytecode can be lazily deserialized.
- static constexpr bool IsLazy(Bytecode bytecode) {
- // Currently, all handlers are deserialized lazily.
- return true;
- }
-
// Returns true if the bytecode returns.
static constexpr bool Returns(Bytecode bytecode) {
#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
@@ -801,6 +805,7 @@ class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
case Bytecode::kCallJSRuntime:
return ConvertReceiverMode::kNullOrUndefined;
case Bytecode::kCallAnyReceiver:
+ case Bytecode::kCallNoFeedback:
case Bytecode::kConstruct:
case Bytecode::kCallWithSpread:
case Bytecode::kConstructWithSpread:
diff --git a/deps/v8/src/interpreter/constant-array-builder.h b/deps/v8/src/interpreter/constant-array-builder.h
index 3f3d38ce6e..f06983abfa 100644
--- a/deps/v8/src/interpreter/constant-array-builder.h
+++ b/deps/v8/src/interpreter/constant-array-builder.h
@@ -36,7 +36,7 @@ namespace interpreter {
// interpreter. Each instance of this class is intended to be used to
// generate exactly one FixedArray of constants via the ToFixedArray
// method.
-class V8_EXPORT_PRIVATE ConstantArrayBuilder final BASE_EMBEDDED {
+class V8_EXPORT_PRIVATE ConstantArrayBuilder final {
public:
// Capacity of the 8-bit operand slice.
static const size_t k8BitCapacity = 1u << kBitsPerByte;
diff --git a/deps/v8/src/interpreter/control-flow-builders.h b/deps/v8/src/interpreter/control-flow-builders.h
index 405e81bc76..fdc57776a8 100644
--- a/deps/v8/src/interpreter/control-flow-builders.h
+++ b/deps/v8/src/interpreter/control-flow-builders.h
@@ -16,11 +16,11 @@ namespace v8 {
namespace internal {
namespace interpreter {
-class V8_EXPORT_PRIVATE ControlFlowBuilder BASE_EMBEDDED {
+class V8_EXPORT_PRIVATE ControlFlowBuilder {
public:
explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
: builder_(builder) {}
- virtual ~ControlFlowBuilder() {}
+ virtual ~ControlFlowBuilder() = default;
protected:
BytecodeArrayBuilder* builder() const { return builder_; }
@@ -41,7 +41,7 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder
break_labels_(builder->zone()),
node_(node),
block_coverage_builder_(block_coverage_builder) {}
- virtual ~BreakableControlFlowBuilder();
+ ~BreakableControlFlowBuilder() override;
// This method is called when visiting break statements in the AST.
// Inserts a jump to an unbound label that is patched when the corresponding
@@ -113,7 +113,7 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
node, SourceRangeKind::kBody);
}
}
- ~LoopBuilder();
+ ~LoopBuilder() override;
void LoopHeader();
void LoopBody();
@@ -149,7 +149,7 @@ class V8_EXPORT_PRIVATE SwitchBuilder final
case_sites_(builder->zone()) {
case_sites_.resize(number_of_cases);
}
- ~SwitchBuilder();
+ ~SwitchBuilder() override; // NOLINT (modernize-use-equals-default)
// This method should be called by the SwitchBuilder owner when the case
// statement with |index| is emitted to update the case jump site.
@@ -186,7 +186,7 @@ class V8_EXPORT_PRIVATE TryCatchBuilder final : public ControlFlowBuilder {
block_coverage_builder_(block_coverage_builder),
statement_(statement) {}
- ~TryCatchBuilder();
+ ~TryCatchBuilder() override;
void BeginTry(Register context);
void EndTry();
@@ -217,7 +217,7 @@ class V8_EXPORT_PRIVATE TryFinallyBuilder final : public ControlFlowBuilder {
block_coverage_builder_(block_coverage_builder),
statement_(statement) {}
- ~TryFinallyBuilder();
+ ~TryFinallyBuilder() override;
void BeginTry(Register context);
void LeaveTry();
@@ -260,7 +260,7 @@ class V8_EXPORT_PRIVATE ConditionalControlFlowBuilder final
node, SourceRangeKind::kElse);
}
}
- ~ConditionalControlFlowBuilder();
+ ~ConditionalControlFlowBuilder() override;
BytecodeLabels* then_labels() { return &then_labels_; }
BytecodeLabels* else_labels() { return &else_labels_; }
diff --git a/deps/v8/src/interpreter/handler-table-builder.h b/deps/v8/src/interpreter/handler-table-builder.h
index 021fefad29..029c8dd1a6 100644
--- a/deps/v8/src/interpreter/handler-table-builder.h
+++ b/deps/v8/src/interpreter/handler-table-builder.h
@@ -21,7 +21,7 @@ class Isolate;
namespace interpreter {
// A helper class for constructing exception handler tables for the interpreter.
-class V8_EXPORT_PRIVATE HandlerTableBuilder final BASE_EMBEDDED {
+class V8_EXPORT_PRIVATE HandlerTableBuilder final {
public:
explicit HandlerTableBuilder(Zone* zone);
diff --git a/deps/v8/src/interpreter/interpreter-assembler.cc b/deps/v8/src/interpreter/interpreter-assembler.cc
index 15e2b1f091..cc8dfb1a30 100644
--- a/deps/v8/src/interpreter/interpreter-assembler.cc
+++ b/deps/v8/src/interpreter/interpreter-assembler.cc
@@ -744,12 +744,12 @@ void InterpreterAssembler::CollectCallableFeedback(Node* target, Node* context,
feedback,
HeapConstant(FeedbackVector::UninitializedSentinel(isolate())));
GotoIf(is_uninitialized, &initialize);
- CSA_ASSERT(this, IsWeakOrClearedHeapObject(feedback));
+ CSA_ASSERT(this, IsWeakOrCleared(feedback));
// If the weak reference is cleared, we have a new chance to become
// monomorphic.
Comment("check if weak reference is cleared");
- Branch(IsClearedWeakHeapObject(feedback), &initialize, &mark_megamorphic);
+ Branch(IsCleared(feedback), &initialize, &mark_megamorphic);
BIND(&initialize);
{
@@ -803,7 +803,7 @@ void InterpreterAssembler::CollectCallableFeedback(Node* target, Node* context,
// MegamorphicSentinel is an immortal immovable object so
// write-barrier is not needed.
Comment("transition to megamorphic");
- DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
+ DCHECK(Heap::RootIsImmortalImmovable(RootIndex::kmegamorphic_symbol));
StoreFeedbackVectorSlot(
feedback_vector, slot_id,
HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
@@ -948,12 +948,12 @@ Node* InterpreterAssembler::Construct(Node* target, Node* context,
GotoIf(is_megamorphic, &construct);
Comment("check if weak reference");
- GotoIfNot(IsWeakOrClearedHeapObject(feedback), &check_allocation_site);
+ GotoIfNot(IsWeakOrCleared(feedback), &check_allocation_site);
// If the weak reference is cleared, we have a new chance to become
// monomorphic.
Comment("check if weak reference is cleared");
- Branch(IsClearedWeakHeapObject(feedback), &initialize, &mark_megamorphic);
+ Branch(IsCleared(feedback), &initialize, &mark_megamorphic);
BIND(&check_allocation_site);
{
@@ -976,7 +976,7 @@ Node* InterpreterAssembler::Construct(Node* target, Node* context,
// Check if it is uninitialized.
Comment("check if uninitialized");
Node* is_uninitialized =
- WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex));
+ WordEqual(feedback, LoadRoot(RootIndex::kuninitialized_symbol));
Branch(is_uninitialized, &initialize, &mark_megamorphic);
}
@@ -1054,7 +1054,7 @@ Node* InterpreterAssembler::Construct(Node* target, Node* context,
// MegamorphicSentinel is an immortal immovable object so
// write-barrier is not needed.
Comment("transition to megamorphic");
- DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
+ DCHECK(Heap::RootIsImmortalImmovable(RootIndex::kmegamorphic_symbol));
StoreFeedbackVectorSlot(
feedback_vector, slot_id,
HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
@@ -1074,8 +1074,8 @@ Node* InterpreterAssembler::Construct(Node* target, Node* context,
isolate(), InterpreterPushArgsMode::kArrayFunction);
Node* code_target = HeapConstant(callable.code());
var_result.Bind(CallStub(callable.descriptor(), code_target, context,
- args.reg_count(), new_target, target,
- var_site.value(), args.base_reg_location()));
+ args.reg_count(), args.base_reg_location(), target,
+ new_target, var_site.value()));
Goto(&return_result);
}
@@ -1087,8 +1087,8 @@ Node* InterpreterAssembler::Construct(Node* target, Node* context,
isolate(), InterpreterPushArgsMode::kOther);
Node* code_target = HeapConstant(callable.code());
var_result.Bind(CallStub(callable.descriptor(), code_target, context,
- args.reg_count(), new_target, target,
- UndefinedConstant(), args.base_reg_location()));
+ args.reg_count(), args.base_reg_location(), target,
+ new_target, UndefinedConstant()));
Goto(&return_result);
}
@@ -1127,19 +1127,19 @@ Node* InterpreterAssembler::ConstructWithSpread(Node* target, Node* context,
GotoIf(is_megamorphic, &construct);
Comment("check if weak reference");
- GotoIfNot(IsWeakOrClearedHeapObject(feedback), &check_initialized);
+ GotoIfNot(IsWeakOrCleared(feedback), &check_initialized);
// If the weak reference is cleared, we have a new chance to become
// monomorphic.
Comment("check if weak reference is cleared");
- Branch(IsClearedWeakHeapObject(feedback), &initialize, &mark_megamorphic);
+ Branch(IsCleared(feedback), &initialize, &mark_megamorphic);
BIND(&check_initialized);
{
// Check if it is uninitialized.
Comment("check if uninitialized");
Node* is_uninitialized =
- WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex));
+ WordEqual(feedback, LoadRoot(RootIndex::kuninitialized_symbol));
Branch(is_uninitialized, &initialize, &mark_megamorphic);
}
@@ -1195,7 +1195,7 @@ Node* InterpreterAssembler::ConstructWithSpread(Node* target, Node* context,
// MegamorphicSentinel is an immortal immovable object so
// write-barrier is not needed.
Comment("transition to megamorphic");
- DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
+ DCHECK(Heap::RootIsImmortalImmovable(RootIndex::kmegamorphic_symbol));
StoreFeedbackVectorSlot(
feedback_vector, slot_id,
HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
@@ -1212,8 +1212,8 @@ Node* InterpreterAssembler::ConstructWithSpread(Node* target, Node* context,
isolate(), InterpreterPushArgsMode::kWithFinalSpread);
Node* code_target = HeapConstant(callable.code());
return CallStub(callable.descriptor(), code_target, context, args.reg_count(),
- new_target, target, UndefinedConstant(),
- args.base_reg_location());
+ args.base_reg_location(), target, new_target,
+ UndefinedConstant());
}
Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context,
@@ -1705,7 +1705,7 @@ Node* InterpreterAssembler::ImportRegisterFile(
StoreRegister(value, reg_index);
StoreFixedArrayElement(array, array_index,
- LoadRoot(Heap::kStaleRegisterRootIndex));
+ LoadRoot(RootIndex::kStaleRegister));
var_index = IntPtrAdd(index, IntPtrConstant(1));
Goto(&loop);
diff --git a/deps/v8/src/interpreter/interpreter-generator.cc b/deps/v8/src/interpreter/interpreter-generator.cc
index afca2a8a32..d2dab6d8d8 100644
--- a/deps/v8/src/interpreter/interpreter-generator.cc
+++ b/deps/v8/src/interpreter/interpreter-generator.cc
@@ -9,6 +9,7 @@
#include "src/builtins/builtins-arguments-gen.h"
#include "src/builtins/builtins-constructor-gen.h"
+#include "src/builtins/builtins-iterator-gen.h"
#include "src/code-events.h"
#include "src/code-factory.h"
#include "src/debug/debug.h"
@@ -517,6 +518,18 @@ IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
}
}
+// LdaPropertyNofeedback <object> <slot>
+//
+// Calls the GetProperty builtin for <object> and the key in the accumulator.
+IGNITION_HANDLER(LdaNamedPropertyNoFeedback, InterpreterAssembler) {
+ Node* object = LoadRegisterAtOperandIndex(0);
+ Node* name = LoadConstantPoolEntryAtOperandIndex(1);
+ Node* context = GetContext();
+ Node* result = CallBuiltin(Builtins::kGetProperty, context, object, name);
+ SetAccumulator(result);
+ Dispatch();
+}
+
// KeyedLoadIC <object> <slot>
//
// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
@@ -582,6 +595,24 @@ IGNITION_HANDLER(StaNamedOwnProperty, InterpreterStoreNamedPropertyAssembler) {
StaNamedProperty(ic);
}
+// StaNamedPropertyNoFeedback <object> <name_index>
+//
+// Calls the SetPropertyBuiltin for <object> and the name in constant pool entry
+// <name_index> with the value in the accumulator.
+IGNITION_HANDLER(StaNamedPropertyNoFeedback,
+ InterpreterStoreNamedPropertyAssembler) {
+ Node* object = LoadRegisterAtOperandIndex(0);
+ Node* name = LoadConstantPoolEntryAtOperandIndex(1);
+ Node* value = GetAccumulator();
+ Node* language_mode = SmiFromInt32(BytecodeOperandFlag(2));
+ Node* context = GetContext();
+
+ Node* result = CallRuntime(Runtime::kSetNamedProperty, context, object, name,
+ value, language_mode);
+ SetAccumulator(result);
+ Dispatch();
+}
+
// StaKeyedProperty <object> <key> <slot>
//
// Calls the KeyedStoreIC at FeedbackVector slot <slot> for <object> and
@@ -1122,7 +1153,7 @@ class UnaryNumericOpAssembler : public InterpreterAssembler {
OperandScale operand_scale)
: InterpreterAssembler(state, bytecode, operand_scale) {}
- virtual ~UnaryNumericOpAssembler() {}
+ virtual ~UnaryNumericOpAssembler() = default;
// Must return a tagged value.
virtual TNode<Number> SmiOp(TNode<Smi> smi_value, Variable* var_feedback,
@@ -1273,7 +1304,7 @@ IGNITION_HANDLER(Negate, NegateAssemblerImpl) { UnaryOpWithFeedback(); }
IGNITION_HANDLER(ToName, InterpreterAssembler) {
Node* object = GetAccumulator();
Node* context = GetContext();
- Node* result = ToName(context, object);
+ Node* result = CallBuiltin(Builtins::kToName, context, object);
StoreRegisterAtOperandIndex(result, 0);
Dispatch();
}
@@ -1501,6 +1532,16 @@ class InterpreterJSCallAssembler : public InterpreterAssembler {
CallJSAndDispatch(function, context, args, receiver_mode);
}
+ // Generates code to perform a JS call without collecting feedback.
+ void JSCallNoFeedback(ConvertReceiverMode receiver_mode) {
+ Node* function = LoadRegisterAtOperandIndex(0);
+ RegListNodePair args = GetRegisterListAtOperandIndex(1);
+ Node* context = GetContext();
+
+ // Call the function and dispatch to the next handler.
+ CallJSAndDispatch(function, context, args, receiver_mode);
+ }
+
// Generates code to perform a JS call with a known number of arguments that
// collects type feedback.
void JSCallN(int arg_count, ConvertReceiverMode receiver_mode) {
@@ -1590,6 +1631,10 @@ IGNITION_HANDLER(CallUndefinedReceiver2, InterpreterJSCallAssembler) {
JSCallN(2, ConvertReceiverMode::kNullOrUndefined);
}
+IGNITION_HANDLER(CallNoFeedback, InterpreterJSCallAssembler) {
+ JSCallNoFeedback(ConvertReceiverMode::kAny);
+}
+
// CallRuntime <function_id> <first_arg> <arg_count>
//
// Call the runtime function |function_id| with the first argument in
@@ -2381,6 +2426,18 @@ IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
Dispatch();
}
+// CreateArrayFromIterable
+//
+// Spread the given iterable from the accumulator into a new JSArray.
+IGNITION_HANDLER(CreateArrayFromIterable, InterpreterAssembler) {
+ Node* iterable = GetAccumulator();
+ Node* context = GetContext();
+ Node* result =
+ CallBuiltin(Builtins::kIterableToListWithSymbolLookup, context, iterable);
+ SetAccumulator(result);
+ Dispatch();
+}
+
// CreateObjectLiteral <element_idx> <literal_idx> <flags>
//
// Creates an object literal for literal index <literal_idx> with
@@ -3128,7 +3185,8 @@ IGNITION_HANDLER(ResumeGenerator, InterpreterAssembler) {
Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode,
OperandScale operand_scale,
- int builtin_index) {
+ int builtin_index,
+ const AssemblerOptions& options) {
Zone zone(isolate->allocator(), ZONE_NAME);
compiler::CodeAssemblerState state(
isolate, &zone, InterpreterDispatchDescriptor{}, Code::BYTECODE_HANDLER,
@@ -3147,8 +3205,7 @@ Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode,
#undef CALL_GENERATOR
}
- Handle<Code> code = compiler::CodeAssembler::GenerateCode(
- &state, AssemblerOptions::Default(isolate));
+ Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state, options);
PROFILE(isolate, CodeCreateEvent(
CodeEventListener::BYTECODE_HANDLER_TAG,
AbstractCode::cast(*code),
@@ -3195,7 +3252,9 @@ class DeserializeLazyAssembler : public InterpreterAssembler {
} // namespace
Handle<Code> GenerateDeserializeLazyHandler(Isolate* isolate,
- OperandScale operand_scale) {
+ OperandScale operand_scale,
+ int builtin_index,
+ const AssemblerOptions& options) {
Zone zone(isolate->allocator(), ZONE_NAME);
std::string debug_name = std::string("DeserializeLazy");
@@ -3210,11 +3269,11 @@ Handle<Code> GenerateDeserializeLazyHandler(Isolate* isolate,
debug_name.c_str(),
FLAG_untrusted_code_mitigations
? PoisoningMitigationLevel::kPoisonCriticalOnly
- : PoisoningMitigationLevel::kDontPoison);
+ : PoisoningMitigationLevel::kDontPoison,
+ 0, builtin_index);
DeserializeLazyAssembler::Generate(&state, operand_scale);
- Handle<Code> code = compiler::CodeAssembler::GenerateCode(
- &state, AssemblerOptions::Default(isolate));
+ Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state, options);
PROFILE(isolate,
CodeCreateEvent(CodeEventListener::BYTECODE_HANDLER_TAG,
AbstractCode::cast(*code), debug_name.c_str()));
diff --git a/deps/v8/src/interpreter/interpreter-generator.h b/deps/v8/src/interpreter/interpreter-generator.h
index bc3793a45f..a41e89f250 100644
--- a/deps/v8/src/interpreter/interpreter-generator.h
+++ b/deps/v8/src/interpreter/interpreter-generator.h
@@ -10,14 +10,19 @@
namespace v8 {
namespace internal {
+
+struct AssemblerOptions;
+
namespace interpreter {
extern Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode,
OperandScale operand_scale,
- int builtin_index);
+ int builtin_index,
+ const AssemblerOptions& options);
-extern Handle<Code> GenerateDeserializeLazyHandler(Isolate* isolate,
- OperandScale operand_scale);
+extern Handle<Code> GenerateDeserializeLazyHandler(
+ Isolate* isolate, OperandScale operand_scale, int builtin_index,
+ const AssemblerOptions& options);
} // namespace interpreter
} // namespace internal
diff --git a/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc b/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc
index 55e554e2e0..3e261bea9f 100644
--- a/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc
+++ b/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc
@@ -159,12 +159,6 @@ Node* IntrinsicsGenerator::IsArray(
return IsInstanceType(input, JS_ARRAY_TYPE);
}
-Node* IntrinsicsGenerator::IsJSProxy(
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
- Node* input = __ LoadRegisterFromRegisterList(args, 0);
- return IsInstanceType(input, JS_PROXY_TYPE);
-}
-
Node* IntrinsicsGenerator::IsTypedArray(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
Node* input = __ LoadRegisterFromRegisterList(args, 0);
@@ -212,12 +206,6 @@ Node* IntrinsicsGenerator::HasProperty(
args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
}
-Node* IntrinsicsGenerator::GetProperty(
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
- return IntrinsicAsStubCall(
- args, context, Builtins::CallableFor(isolate(), Builtins::kGetProperty));
-}
-
Node* IntrinsicsGenerator::RejectPromise(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
return IntrinsicAsStubCall(
@@ -244,18 +232,6 @@ Node* IntrinsicsGenerator::ToLength(
args, context, Builtins::CallableFor(isolate(), Builtins::kToLength));
}
-Node* IntrinsicsGenerator::ToInteger(
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
- return IntrinsicAsStubCall(
- args, context, Builtins::CallableFor(isolate(), Builtins::kToInteger));
-}
-
-Node* IntrinsicsGenerator::ToNumber(
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
- return IntrinsicAsStubCall(
- args, context, Builtins::CallableFor(isolate(), Builtins::kToNumber));
-}
-
Node* IntrinsicsGenerator::ToObject(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
return IntrinsicAsStubCall(
@@ -336,15 +312,6 @@ Node* IntrinsicsGenerator::CreateJSGeneratorObject(
Builtins::kCreateGeneratorObject);
}
-Node* IntrinsicsGenerator::GeneratorGetInputOrDebugPos(
- const InterpreterAssembler::RegListNodePair& args, Node* context) {
- Node* generator = __ LoadRegisterFromRegisterList(args, 0);
- Node* const value =
- __ LoadObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset);
-
- return value;
-}
-
Node* IntrinsicsGenerator::GeneratorGetResumeMode(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
Node* generator = __ LoadRegisterFromRegisterList(args, 0);
diff --git a/deps/v8/src/interpreter/interpreter-intrinsics.h b/deps/v8/src/interpreter/interpreter-intrinsics.h
index 04f662f0df..608b0afcac 100644
--- a/deps/v8/src/interpreter/interpreter-intrinsics.h
+++ b/deps/v8/src/interpreter/interpreter-intrinsics.h
@@ -19,16 +19,13 @@ namespace interpreter {
V(AsyncGeneratorYield, async_generator_yield, 3) \
V(CreateJSGeneratorObject, create_js_generator_object, 2) \
V(GeneratorGetResumeMode, generator_get_resume_mode, 1) \
- V(GeneratorGetInputOrDebugPos, generator_get_input_or_debug_pos, 1) \
V(GeneratorClose, generator_close, 1) \
V(GetImportMetaObject, get_import_meta_object, 0) \
V(Call, call, -1) \
V(CreateIterResultObject, create_iter_result_object, 2) \
V(CreateAsyncFromSyncIterator, create_async_from_sync_iterator, 1) \
V(HasProperty, has_property, 2) \
- V(GetProperty, get_property, 2) \
V(IsArray, is_array, 1) \
- V(IsJSProxy, is_js_proxy, 1) \
V(IsJSReceiver, is_js_receiver, 1) \
V(IsSmi, is_smi, 1) \
V(IsTypedArray, is_typed_array, 1) \
@@ -36,8 +33,6 @@ namespace interpreter {
V(ResolvePromise, resolve_promise, 2) \
V(ToString, to_string, 1) \
V(ToLength, to_length, 1) \
- V(ToInteger, to_integer, 1) \
- V(ToNumber, to_number, 1) \
V(ToObject, to_object, 1)
class IntrinsicsHelper {
diff --git a/deps/v8/src/interpreter/interpreter.cc b/deps/v8/src/interpreter/interpreter.cc
index 0446ed494d..ca53fa674c 100644
--- a/deps/v8/src/interpreter/interpreter.cc
+++ b/deps/v8/src/interpreter/interpreter.cc
@@ -7,6 +7,7 @@
#include <fstream>
#include <memory>
+#include "builtins-generated/bytecodes-builtins-list.h"
#include "src/ast/prettyprinter.h"
#include "src/bootstrapper.h"
#include "src/compiler.h"
@@ -59,41 +60,47 @@ Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) {
}
}
+namespace {
+
+int BuiltinIndexFromBytecode(Bytecode bytecode, OperandScale operand_scale) {
+ int index = BytecodeOperands::OperandScaleAsIndex(operand_scale) *
+ kNumberOfBytecodeHandlers +
+ static_cast<int>(bytecode);
+ int offset = kBytecodeToBuiltinsMapping[index];
+ return offset >= 0 ? Builtins::kFirstBytecodeHandler + offset
+ : Builtins::kIllegalHandler;
+}
+
+} // namespace
+
Code* Interpreter::GetAndMaybeDeserializeBytecodeHandler(
Bytecode bytecode, OperandScale operand_scale) {
- Code* code = GetBytecodeHandler(bytecode, operand_scale);
+ int builtin_index = BuiltinIndexFromBytecode(bytecode, operand_scale);
+ Builtins* builtins = isolate_->builtins();
+ Code* code = builtins->builtin(builtin_index);
// Already deserialized? Then just return the handler.
- if (!isolate_->heap()->IsDeserializeLazyHandler(code)) return code;
+ if (!Builtins::IsLazyDeserializer(code)) return code;
- DCHECK(FLAG_lazy_handler_deserialization);
+ DCHECK(FLAG_lazy_deserialization);
DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
- code = Snapshot::DeserializeHandler(isolate_, bytecode, operand_scale);
+ code = Snapshot::DeserializeBuiltin(isolate_, builtin_index);
DCHECK(code->IsCode());
DCHECK_EQ(code->kind(), Code::BYTECODE_HANDLER);
- DCHECK(!isolate_->heap()->IsDeserializeLazyHandler(code));
+ DCHECK(!Builtins::IsLazyDeserializer(code));
SetBytecodeHandler(bytecode, operand_scale, code);
return code;
}
-Code* Interpreter::GetBytecodeHandler(Bytecode bytecode,
- OperandScale operand_scale) {
- DCHECK(IsDispatchTableInitialized());
- DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
- size_t index = GetDispatchTableIndex(bytecode, operand_scale);
- Address code_entry = dispatch_table_[index];
- return Code::GetCodeFromTargetAddress(code_entry);
-}
-
void Interpreter::SetBytecodeHandler(Bytecode bytecode,
OperandScale operand_scale,
Code* handler) {
DCHECK(handler->kind() == Code::BYTECODE_HANDLER);
size_t index = GetDispatchTableIndex(bytecode, operand_scale);
- dispatch_table_[index] = handler->entry();
+ dispatch_table_[index] = handler->InstructionStart();
}
// static
@@ -101,20 +108,17 @@ size_t Interpreter::GetDispatchTableIndex(Bytecode bytecode,
OperandScale operand_scale) {
static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte;
size_t index = static_cast<size_t>(bytecode);
- switch (operand_scale) {
- case OperandScale::kSingle:
- return index;
- case OperandScale::kDouble:
- return index + kEntriesPerOperandScale;
- case OperandScale::kQuadruple:
- return index + 2 * kEntriesPerOperandScale;
- }
- UNREACHABLE();
+ return index + BytecodeOperands::OperandScaleAsIndex(operand_scale) *
+ kEntriesPerOperandScale;
}
void Interpreter::IterateDispatchTable(RootVisitor* v) {
for (int i = 0; i < kDispatchTableSize; i++) {
Address code_entry = dispatch_table_[i];
+
+ // If the handler is embedded, it is immovable.
+ if (InstructionStream::PcIsOffHeap(isolate_, code_entry)) continue;
+
Object* code = code_entry == kNullAddress
? nullptr
: Code::GetCodeFromTargetAddress(code_entry);
@@ -229,6 +233,52 @@ UnoptimizedCompilationJob* Interpreter::NewCompilationJob(
eager_inner_literals);
}
+void Interpreter::ForEachBytecode(
+ const std::function<void(Bytecode, OperandScale)>& f) {
+ constexpr OperandScale kOperandScales[] = {
+#define VALUE(Name, _) OperandScale::k##Name,
+ OPERAND_SCALE_LIST(VALUE)
+#undef VALUE
+ };
+
+ for (OperandScale operand_scale : kOperandScales) {
+ for (int i = 0; i < Bytecodes::kBytecodeCount; i++) {
+ f(Bytecodes::FromByte(i), operand_scale);
+ }
+ }
+}
+
+void Interpreter::InitializeDispatchTable() {
+ Builtins* builtins = isolate_->builtins();
+ Code* illegal = builtins->builtin(Builtins::kIllegalHandler);
+ int builtin_id = Builtins::kFirstBytecodeHandler;
+ ForEachBytecode([=, &builtin_id](Bytecode bytecode,
+ OperandScale operand_scale) {
+ Code* handler = illegal;
+ if (Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
+#ifdef DEBUG
+ std::string builtin_name(Builtins::name(builtin_id));
+ std::string expected_name =
+ Bytecodes::ToString(bytecode, operand_scale, "") + "Handler";
+ DCHECK_EQ(expected_name, builtin_name);
+#endif
+ handler = builtins->builtin(builtin_id++);
+ }
+ SetBytecodeHandler(bytecode, operand_scale, handler);
+ });
+ DCHECK(builtin_id == Builtins::builtin_count);
+ DCHECK(IsDispatchTableInitialized());
+
+#if defined(V8_USE_SNAPSHOT) && !defined(V8_USE_SNAPSHOT_WITH_UNWINDING_INFO)
+ if (!isolate_->serializer_enabled() && FLAG_perf_prof_unwinding_info) {
+ StdoutStream{}
+ << "Warning: The --perf-prof-unwinding-info flag can be passed at "
+ "mksnapshot time to get better results."
+ << std::endl;
+ }
+#endif
+}
+
bool Interpreter::IsDispatchTableInitialized() const {
return dispatch_table_[0] != kNullAddress;
}
diff --git a/deps/v8/src/interpreter/interpreter.h b/deps/v8/src/interpreter/interpreter.h
index 5ded893798..5023b0ef00 100644
--- a/deps/v8/src/interpreter/interpreter.h
+++ b/deps/v8/src/interpreter/interpreter.h
@@ -36,7 +36,7 @@ class InterpreterAssembler;
class Interpreter {
public:
explicit Interpreter(Isolate* isolate);
- virtual ~Interpreter() {}
+ virtual ~Interpreter() = default;
// Returns the interrupt budget which should be used for the profiler counter.
static int InterruptBudget();
@@ -54,9 +54,6 @@ class Interpreter {
Code* GetAndMaybeDeserializeBytecodeHandler(Bytecode bytecode,
OperandScale operand_scale);
- // Return bytecode handler for |bytecode| and |operand_scale|.
- Code* GetBytecodeHandler(Bytecode bytecode, OperandScale operand_scale);
-
// Set the bytecode handler for |bytecode| and |operand_scale|.
void SetBytecodeHandler(Bytecode bytecode, OperandScale operand_scale,
Code* handler);
@@ -69,6 +66,10 @@ class Interpreter {
V8_EXPORT_PRIVATE Local<v8::Object> GetDispatchCountersObject();
+ void ForEachBytecode(const std::function<void(Bytecode, OperandScale)>& f);
+
+ void InitializeDispatchTable();
+
bool IsDispatchTableInitialized() const;
Address dispatch_table_address() {
diff --git a/deps/v8/src/interpreter/setup-interpreter-internal.cc b/deps/v8/src/interpreter/setup-interpreter-internal.cc
deleted file mode 100644
index 8f2b565c00..0000000000
--- a/deps/v8/src/interpreter/setup-interpreter-internal.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2017 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/setup-interpreter.h"
-
-#include "src/handles-inl.h"
-#include "src/interpreter/bytecodes.h"
-#include "src/interpreter/interpreter-generator.h"
-#include "src/interpreter/interpreter.h"
-#include "src/objects-inl.h"
-
-namespace v8 {
-namespace internal {
-namespace interpreter {
-
-namespace {
-void PrintBuiltinSize(Bytecode bytecode, OperandScale operand_scale,
- Handle<Code> code) {
- PrintF(stdout, "Ignition Handler, %s, %d\n",
- Bytecodes::ToString(bytecode, operand_scale).c_str(),
- code->InstructionSize());
-}
-} // namespace
-
-// static
-void SetupInterpreter::InstallBytecodeHandlers(Interpreter* interpreter) {
- DCHECK(!interpreter->IsDispatchTableInitialized());
- HandleScope scope(interpreter->isolate_);
- // Canonicalize handles, so that we can share constant pool entries pointing
- // to code targets without dereferencing their handles.
- CanonicalHandleScope canonical(interpreter->isolate_);
- Address* dispatch_table = interpreter->dispatch_table_;
-
- // Generate bytecode handlers for all bytecodes and scales.
- const OperandScale kOperandScales[] = {
-#define VALUE(Name, _) OperandScale::k##Name,
- OPERAND_SCALE_LIST(VALUE)
-#undef VALUE
- };
-
- for (OperandScale operand_scale : kOperandScales) {
-#define GENERATE_CODE(Name, ...) \
- InstallBytecodeHandler(interpreter->isolate_, dispatch_table, \
- Bytecode::k##Name, operand_scale);
- BYTECODE_LIST(GENERATE_CODE)
-#undef GENERATE_CODE
- }
-
- // Fill unused entries will the illegal bytecode handler.
- size_t illegal_index = Interpreter::GetDispatchTableIndex(
- Bytecode::kIllegal, OperandScale::kSingle);
- for (size_t index = 0; index < Interpreter::kDispatchTableSize; ++index) {
- if (dispatch_table[index] == kNullAddress) {
- dispatch_table[index] = dispatch_table[illegal_index];
- }
- }
-
- // Generate the DeserializeLazy handlers, one for each operand scale.
- Heap* heap = interpreter->isolate_->heap();
- DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler());
- heap->SetDeserializeLazyHandler(*GenerateDeserializeLazyHandler(
- interpreter->isolate_, OperandScale::kSingle));
- DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler_wide());
- heap->SetDeserializeLazyHandlerWide(*GenerateDeserializeLazyHandler(
- interpreter->isolate_, OperandScale::kDouble));
- DCHECK_EQ(Smi::kZero, heap->deserialize_lazy_handler_extra_wide());
- heap->SetDeserializeLazyHandlerExtraWide(*GenerateDeserializeLazyHandler(
- interpreter->isolate_, OperandScale::kQuadruple));
-
- // Initialization should have been successful.
- DCHECK(interpreter->IsDispatchTableInitialized());
-}
-
-// static
-void SetupInterpreter::InstallBytecodeHandler(Isolate* isolate,
- Address* dispatch_table,
- Bytecode bytecode,
- OperandScale operand_scale) {
- if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
-
- size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
- // Here we explicitly set the bytecode handler to not be a builtin with an
- // index of kNoBuiltinId.
- // TODO(delphick): Use builtins version instead.
- Handle<Code> code = GenerateBytecodeHandler(isolate, bytecode, operand_scale,
- Builtins::kNoBuiltinId);
- dispatch_table[index] = code->entry();
-
- if (FLAG_print_builtin_size) PrintBuiltinSize(bytecode, operand_scale, code);
-
-#ifdef ENABLE_DISASSEMBLER
- if (FLAG_print_builtin_code) {
- std::string name = Bytecodes::ToString(bytecode, operand_scale);
- code->PrintBuiltinCode(isolate, name.c_str());
- }
-#endif // ENABLE_DISASSEMBLER
-}
-
-} // namespace interpreter
-} // namespace internal
-} // namespace v8
diff --git a/deps/v8/src/interpreter/setup-interpreter.h b/deps/v8/src/interpreter/setup-interpreter.h
deleted file mode 100644
index 19b03f7f7f..0000000000
--- a/deps/v8/src/interpreter/setup-interpreter.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef V8_INTERPRETER_SETUP_INTERPRETER_H_
-#define V8_INTERPRETER_SETUP_INTERPRETER_H_
-
-#include "src/interpreter/bytecode-operands.h"
-#include "src/interpreter/bytecodes.h"
-
-namespace v8 {
-namespace internal {
-namespace interpreter {
-
-class Interpreter;
-
-class SetupInterpreter {
- public:
- static void InstallBytecodeHandlers(Interpreter* interpreter);
-
- private:
- // Generates handler for given |bytecode| and |operand_scale|
- // and installs it into the |dispatch_table|.
- static void InstallBytecodeHandler(Isolate* isolate, Address* dispatch_table,
- Bytecode bytecode,
- OperandScale operand_scale);
-};
-
-} // namespace interpreter
-} // namespace internal
-} // namespace v8
-
-#endif // V8_INTERPRETER_SETUP_INTERPRETER_H_