diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-12-04 08:20:37 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2018-12-06 15:23:33 +0100 |
commit | 9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3 (patch) | |
tree | 2b0c843168dafb939d8df8a15b2aa72b76dee51d /deps/v8/src/interpreter | |
parent | b8fbe69db1292307adb2c2b2e0d5ef48c4ab2faf (diff) | |
download | android-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')
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_ |