diff options
Diffstat (limited to 'deps/v8/src/interpreter')
-rw-r--r-- | deps/v8/src/interpreter/bytecode-array-builder.cc | 7 | ||||
-rw-r--r-- | deps/v8/src/interpreter/bytecode-array-builder.h | 2 | ||||
-rw-r--r-- | deps/v8/src/interpreter/bytecode-array-writer.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/interpreter/bytecode-generator.cc | 198 | ||||
-rw-r--r-- | deps/v8/src/interpreter/bytecode-generator.h | 11 | ||||
-rw-r--r-- | deps/v8/src/interpreter/bytecodes.h | 2 | ||||
-rw-r--r-- | deps/v8/src/interpreter/constant-array-builder.h | 1 | ||||
-rw-r--r-- | deps/v8/src/interpreter/interpreter-assembler.cc | 50 | ||||
-rw-r--r-- | deps/v8/src/interpreter/interpreter-assembler.h | 8 | ||||
-rw-r--r-- | deps/v8/src/interpreter/interpreter-generator.cc | 61 | ||||
-rw-r--r-- | deps/v8/src/interpreter/interpreter-generator.h | 3 | ||||
-rw-r--r-- | deps/v8/src/interpreter/interpreter-intrinsics-generator.cc | 19 | ||||
-rw-r--r-- | deps/v8/src/interpreter/interpreter-intrinsics.h | 3 | ||||
-rw-r--r-- | deps/v8/src/interpreter/setup-interpreter-internal.cc | 6 |
14 files changed, 262 insertions, 111 deletions
diff --git a/deps/v8/src/interpreter/bytecode-array-builder.cc b/deps/v8/src/interpreter/bytecode-array-builder.cc index b0162c77ad..33731599c8 100644 --- a/deps/v8/src/interpreter/bytecode-array-builder.cc +++ b/deps/v8/src/interpreter/bytecode-array-builder.cc @@ -986,6 +986,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyObjectLiteral() { return *this; } +BytecodeArrayBuilder& BytecodeArrayBuilder::CloneObject(Register source, + int flags, + int feedback_slot) { + OutputCloneObject(source, flags, feedback_slot); + return *this; +} + BytecodeArrayBuilder& BytecodeArrayBuilder::GetTemplateObject( size_t template_object_description_entry, int feedback_slot) { OutputGetTemplateObject(template_object_description_entry, feedback_slot); diff --git a/deps/v8/src/interpreter/bytecode-array-builder.h b/deps/v8/src/interpreter/bytecode-array-builder.h index f34f6f3a7d..3feda90495 100644 --- a/deps/v8/src/interpreter/bytecode-array-builder.h +++ b/deps/v8/src/interpreter/bytecode-array-builder.h @@ -238,6 +238,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final { int literal_index, int flags, Register output); BytecodeArrayBuilder& CreateEmptyObjectLiteral(); + BytecodeArrayBuilder& CloneObject(Register source, int flags, + int feedback_slot); // Gets or creates the template for a TemplateObjectDescription which will // be inserted at constant pool index |template_object_description_entry|. diff --git a/deps/v8/src/interpreter/bytecode-array-writer.cc b/deps/v8/src/interpreter/bytecode-array-writer.cc index b44f726e92..3dbd009879 100644 --- a/deps/v8/src/interpreter/bytecode-array-writer.cc +++ b/deps/v8/src/interpreter/bytecode-array-writer.cc @@ -4,7 +4,7 @@ #include "src/interpreter/bytecode-array-writer.h" -#include "src/api.h" +#include "src/api-inl.h" #include "src/interpreter/bytecode-jump-table.h" #include "src/interpreter/bytecode-label.h" #include "src/interpreter/bytecode-node.h" diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc index 79792a3d56..11a19443e1 100644 --- a/deps/v8/src/interpreter/bytecode-generator.cc +++ b/deps/v8/src/interpreter/bytecode-generator.cc @@ -4,7 +4,7 @@ #include "src/interpreter/bytecode-generator.h" -#include "src/api.h" +#include "src/api-inl.h" #include "src/ast/ast-source-ranges.h" #include "src/ast/scopes.h" #include "src/builtins/builtins-constructor.h" @@ -1815,6 +1815,14 @@ void BytecodeGenerator::AddToEagerLiteralsIfEager(FunctionLiteral* literal) { } } +bool BytecodeGenerator::ShouldOptimizeAsOneShot() const { + if (!FLAG_enable_one_shot_optimization) return false; + + if (loop_depth_ > 0) return false; + + return info()->literal()->is_top_level() || info()->literal()->is_iife(); +} + void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr) { size_t class_boilerplate_entry = builder()->AllocateDeferredConstantPoolEntry(); @@ -2097,6 +2105,27 @@ void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { expr->flags()); } +void BytecodeGenerator::BuildCreateObjectLiteral(Register literal, + uint8_t flags, size_t entry) { + if (ShouldOptimizeAsOneShot()) { + RegisterList args = register_allocator()->NewRegisterList(2); + builder() + ->LoadConstantPoolEntry(entry) + .StoreAccumulatorInRegister(args[0]) + .LoadLiteral(Smi::FromInt(flags)) + .StoreAccumulatorInRegister(args[1]) + .CallRuntime(Runtime::kCreateObjectLiteralWithoutAllocationSite, args) + .StoreAccumulatorInRegister(literal); + + } else { + // TODO(cbruni): Directly generate runtime call for literals we cannot + // optimize once the CreateShallowObjectLiteral stub is in sync with the TF + // optimizations. + int literal_index = feedback_index(feedback_spec()->AddLiteralSlot()); + builder()->CreateObjectLiteral(entry, literal_index, flags, literal); + } +} + void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { expr->InitDepthAndFlags(); @@ -2108,42 +2137,63 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { return; } - int literal_index = feedback_index(feedback_spec()->AddLiteralSlot()); // Deep-copy the literal boilerplate. uint8_t flags = CreateObjectLiteralFlags::Encode( expr->ComputeFlags(), expr->IsFastCloningSupported()); Register literal = register_allocator()->NewRegister(); - size_t entry; - // If constant properties is an empty fixed array, use a cached empty fixed - // array to ensure it's only added to the constant pool once. - if (expr->properties_count() == 0) { - entry = builder()->EmptyObjectBoilerplateDescriptionConstantPoolEntry(); + + // Create literal object. + int property_index = 0; + bool clone_object_spread = + expr->properties()->first()->kind() == ObjectLiteral::Property::SPREAD; + if (clone_object_spread) { + // Avoid the slow path for spreads in the following common cases: + // 1) `let obj = { ...source }` + // 2) `let obj = { ...source, override: 1 }` + // 3) `let obj = { ...source, ...overrides }` + RegisterAllocationScope register_scope(this); + Expression* property = expr->properties()->first()->value(); + Register from_value = VisitForRegisterValue(property); + + BytecodeLabels clone_object(zone()); + builder()->JumpIfUndefined(clone_object.New()); + builder()->JumpIfNull(clone_object.New()); + builder()->ToObject(from_value); + + clone_object.Bind(builder()); + int clone_index = feedback_index(feedback_spec()->AddCloneObjectSlot()); + builder()->CloneObject(from_value, flags, clone_index); + builder()->StoreAccumulatorInRegister(literal); + property_index++; } else { - entry = builder()->AllocateDeferredConstantPoolEntry(); - object_literals_.push_back(std::make_pair(expr, entry)); + size_t entry; + // If constant properties is an empty fixed array, use a cached empty fixed + // array to ensure it's only added to the constant pool once. + if (expr->properties_count() == 0) { + entry = builder()->EmptyObjectBoilerplateDescriptionConstantPoolEntry(); + } else { + entry = builder()->AllocateDeferredConstantPoolEntry(); + object_literals_.push_back(std::make_pair(expr, entry)); + } + BuildCreateObjectLiteral(literal, flags, entry); } - // TODO(cbruni): Directly generate runtime call for literals we cannot - // optimize once the CreateShallowObjectLiteral stub is in sync with the TF - // optimizations. - builder()->CreateObjectLiteral(entry, literal_index, flags, literal); // Store computed values into the literal. - int property_index = 0; AccessorTable accessor_table(zone()); for (; property_index < expr->properties()->length(); property_index++) { ObjectLiteral::Property* property = expr->properties()->at(property_index); if (property->is_computed_name()) break; - if (property->IsCompileTimeValue()) continue; + if (!clone_object_spread && property->IsCompileTimeValue()) continue; RegisterAllocationScope inner_register_scope(this); Literal* key = property->key()->AsLiteral(); switch (property->kind()) { case ObjectLiteral::Property::SPREAD: - case ObjectLiteral::Property::CONSTANT: UNREACHABLE(); + case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::MATERIALIZED_LITERAL: - DCHECK(!property->value()->IsCompileTimeValue()); + DCHECK(clone_object_spread || !property->value()->IsCompileTimeValue()); V8_FALLTHROUGH; case ObjectLiteral::Property::COMPUTED: { // It is safe to use [[Put]] here because the boilerplate already @@ -2382,22 +2432,41 @@ void BytecodeGenerator::BuildArrayLiteralElementsInsertion( void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { expr->InitDepthAndFlags(); + uint8_t flags = CreateArrayLiteralFlags::Encode( + expr->IsFastCloningSupported(), expr->ComputeFlags()); - // Deep-copy the literal boilerplate. - int literal_index = feedback_index(feedback_spec()->AddLiteralSlot()); - if (expr->is_empty()) { + 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); } - uint8_t flags = CreateArrayLiteralFlags::Encode( - expr->IsFastCloningSupported(), expr->ComputeFlags()); - size_t entry = builder()->AllocateDeferredConstantPoolEntry(); - builder()->CreateArrayLiteral(entry, literal_index, flags); - array_literals_.push_back(std::make_pair(expr, entry)); - Register literal = register_allocator()->NewRegister(); builder()->StoreAccumulatorInRegister(literal); // Insert all elements except the constant ones, since they are already there. @@ -2751,6 +2820,54 @@ void BytecodeGenerator::BuildVariableAssignment( } } +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); + } else { + FeedbackSlot slot = GetCachedLoadICSlot(property->obj(), name); + builder()->LoadNamedProperty(object, name, feedback_index(slot)); + } +} + +void BytecodeGenerator::BuildStoreNamedProperty(Property* property, + Register object, + const AstRawString* name) { + Register value; + if (!execution_result()->IsEffect()) { + value = register_allocator()->NewRegister(); + builder()->StoreAccumulatorInRegister(value); + } + + 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); + } else { + FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name); + builder()->StoreNamedProperty(object, name, feedback_index(slot), + language_mode()); + } + + if (!execution_result()->IsEffect()) { + builder()->LoadAccumulatorWithRegister(value); + } +} + void BytecodeGenerator::VisitAssignment(Assignment* expr) { DCHECK(expr->target()->IsValidReferenceExpression() || (expr->op() == Token::INIT && expr->target()->IsVariableProxy() && @@ -2812,8 +2929,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) { break; } case NAMED_PROPERTY: { - FeedbackSlot slot = GetCachedLoadICSlot(property->obj(), name); - builder()->LoadNamedProperty(object, name, feedback_index(slot)); + BuildLoadNamedProperty(property, object, name); break; } case KEYED_PROPERTY: { @@ -2863,17 +2979,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) { break; } case NAMED_PROPERTY: { - FeedbackSlot slot = GetCachedStoreICSlot(property->obj(), name); - Register value; - if (!execution_result()->IsEffect()) { - value = register_allocator()->NewRegister(); - builder()->StoreAccumulatorInRegister(value); - } - builder()->StoreNamedProperty(object, name, feedback_index(slot), - language_mode()); - if (!execution_result()->IsEffect()) { - builder()->LoadAccumulatorWithRegister(value); - } + BuildStoreNamedProperty(property, object, name); break; } case KEYED_PROPERTY: { @@ -3339,11 +3445,9 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) { UNREACHABLE(); case NAMED_PROPERTY: { builder()->SetExpressionPosition(property); - builder()->LoadNamedProperty( - obj, property->key()->AsLiteral()->AsRawPropertyName(), - feedback_index(GetCachedLoadICSlot( - property->obj(), - property->key()->AsLiteral()->AsRawPropertyName()))); + const AstRawString* name = + property->key()->AsLiteral()->AsRawPropertyName(); + BuildLoadNamedProperty(property, obj, name); break; } case KEYED_PROPERTY: { @@ -4726,11 +4830,7 @@ void BytecodeGenerator::VisitArgumentsObject(Variable* variable) { // Allocate and initialize a new arguments object and assign to the // {arguments} variable. - CreateArgumentsType type = - is_strict(language_mode()) || !info()->has_simple_parameters() - ? CreateArgumentsType::kUnmappedArguments - : CreateArgumentsType::kMappedArguments; - builder()->CreateArguments(type); + builder()->CreateArguments(closure_scope()->GetArgumentsType()); BuildVariableAssignment(variable, Token::ASSIGN, HoleCheckMode::kElided); } diff --git a/deps/v8/src/interpreter/bytecode-generator.h b/deps/v8/src/interpreter/bytecode-generator.h index c9cee39bb9..47f1f83e12 100644 --- a/deps/v8/src/interpreter/bytecode-generator.h +++ b/deps/v8/src/interpreter/bytecode-generator.h @@ -120,6 +120,11 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { void VisitPropertyLoadForRegister(Register obj, Property* expr, Register destination); + void BuildLoadNamedProperty(Property* property, Register object, + const AstRawString* name); + void BuildStoreNamedProperty(Property* property, Register object, + const AstRawString* name); + void BuildVariableLoad(Variable* variable, HoleCheckMode hole_check_mode, TypeofMode typeof_mode = NOT_INSIDE_TYPEOF); void BuildVariableLoadForAccumulatorValue( @@ -182,6 +187,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ZonePtrList<Expression>* elements, bool skip_constants); + void BuildCreateObjectLiteral(Register literal, uint8_t flags, size_t entry); void AllocateTopLevelRegisters(); void VisitArgumentsObject(Variable* variable); void VisitRestArgumentsArray(Variable* rest); @@ -277,6 +283,11 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { void AddToEagerLiteralsIfEager(FunctionLiteral* literal); + // Checks if the visited expression is one shot, i.e executed only once. Any + // expression either in a top level code or an IIFE that is not within a loop + // is eligible for one shot optimizations. + inline bool ShouldOptimizeAsOneShot() const; + static constexpr ToBooleanMode ToBooleanModeFromTypeHint(TypeHint type_hint) { return type_hint == TypeHint::kBoolean ? ToBooleanMode::kAlreadyBoolean : ToBooleanMode::kConvertToBoolean; diff --git a/deps/v8/src/interpreter/bytecodes.h b/deps/v8/src/interpreter/bytecodes.h index b1ae88c1ba..0e543877f7 100644 --- a/deps/v8/src/interpreter/bytecodes.h +++ b/deps/v8/src/interpreter/bytecodes.h @@ -251,6 +251,8 @@ namespace interpreter { V(CreateObjectLiteral, AccumulatorUse::kNone, OperandType::kIdx, \ OperandType::kIdx, OperandType::kFlag8, OperandType::kRegOut) \ V(CreateEmptyObjectLiteral, AccumulatorUse::kWrite) \ + V(CloneObject, AccumulatorUse::kWrite, OperandType::kReg, \ + OperandType::kFlag8, OperandType::kIdx) \ \ /* Tagged templates */ \ V(GetTemplateObject, AccumulatorUse::kWrite, OperandType::kIdx, \ diff --git a/deps/v8/src/interpreter/constant-array-builder.h b/deps/v8/src/interpreter/constant-array-builder.h index 8f558c4a90..3f3d38ce6e 100644 --- a/deps/v8/src/interpreter/constant-array-builder.h +++ b/deps/v8/src/interpreter/constant-array-builder.h @@ -25,6 +25,7 @@ namespace interpreter { V(AsyncIteratorSymbol, async_iterator_symbol) \ V(ClassFieldsSymbol, class_fields_symbol) \ V(EmptyObjectBoilerplateDescription, empty_object_boilerplate_description) \ + V(EmptyArrayBoilerplateDescription, empty_array_boilerplate_description) \ V(EmptyFixedArray, empty_fixed_array) \ V(HomeObjectSymbol, home_object_symbol) \ V(IteratorSymbol, iterator_symbol) \ diff --git a/deps/v8/src/interpreter/interpreter-assembler.cc b/deps/v8/src/interpreter/interpreter-assembler.cc index 6ea4ba628c..15e2b1f091 100644 --- a/deps/v8/src/interpreter/interpreter-assembler.cc +++ b/deps/v8/src/interpreter/interpreter-assembler.cc @@ -647,8 +647,8 @@ Node* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) { } Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { - Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), - BytecodeArray::kConstantPoolOffset); + TNode<FixedArray> constant_pool = CAST(LoadObjectField( + BytecodeArrayTaggedPointer(), BytecodeArray::kConstantPoolOffset)); return LoadFixedArrayElement(constant_pool, UncheckedCast<IntPtrT>(index), LoadSensitivity::kCritical); } @@ -1599,16 +1599,18 @@ void InterpreterAssembler::AbortIfRegisterCountInvalid( } Node* InterpreterAssembler::ExportParametersAndRegisterFile( - Node* array, const RegListNodePair& registers, - Node* formal_parameter_count) { + TNode<FixedArray> array, const RegListNodePair& registers, + TNode<Int32T> formal_parameter_count) { // Store the formal parameters (without receiver) followed by the // registers into the generator's internal parameters_and_registers field. - formal_parameter_count = ChangeInt32ToIntPtr(formal_parameter_count); + TNode<IntPtrT> formal_parameter_count_intptr = + ChangeInt32ToIntPtr(formal_parameter_count); Node* register_count = ChangeUint32ToWord(registers.reg_count()); if (FLAG_debug_code) { CSA_ASSERT(this, IntPtrEqual(registers.base_reg_location(), RegisterLocation(Register(0)))); - AbortIfRegisterCountInvalid(array, formal_parameter_count, register_count); + AbortIfRegisterCountInvalid(array, formal_parameter_count_intptr, + register_count); } { @@ -1620,13 +1622,14 @@ Node* InterpreterAssembler::ExportParametersAndRegisterFile( Node* reg_base = IntPtrAdd( IntPtrConstant(Register::FromParameterIndex(0, 1).ToOperand() - 1), - formal_parameter_count); + formal_parameter_count_intptr); Goto(&loop); BIND(&loop); { Node* index = var_index.value(); - GotoIfNot(UintPtrLessThan(index, formal_parameter_count), &done_loop); + GotoIfNot(UintPtrLessThan(index, formal_parameter_count_intptr), + &done_loop); Node* reg_index = IntPtrSub(reg_base, index); Node* value = LoadRegister(reg_index); @@ -1657,7 +1660,7 @@ Node* InterpreterAssembler::ExportParametersAndRegisterFile( IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); Node* value = LoadRegister(reg_index); - Node* array_index = IntPtrAdd(formal_parameter_count, index); + Node* array_index = IntPtrAdd(formal_parameter_count_intptr, index); StoreFixedArrayElement(array, array_index, value); var_index.Bind(IntPtrAdd(index, IntPtrConstant(1))); @@ -1669,19 +1672,20 @@ Node* InterpreterAssembler::ExportParametersAndRegisterFile( return array; } -Node* InterpreterAssembler::ImportRegisterFile(Node* array, - const RegListNodePair& registers, - Node* formal_parameter_count) { - formal_parameter_count = ChangeInt32ToIntPtr(formal_parameter_count); - Node* register_count = ChangeUint32ToWord(registers.reg_count()); +Node* InterpreterAssembler::ImportRegisterFile( + TNode<FixedArray> array, const RegListNodePair& registers, + TNode<Int32T> formal_parameter_count) { + TNode<IntPtrT> formal_parameter_count_intptr = + ChangeInt32ToIntPtr(formal_parameter_count); + TNode<UintPtrT> register_count = ChangeUint32ToWord(registers.reg_count()); if (FLAG_debug_code) { CSA_ASSERT(this, IntPtrEqual(registers.base_reg_location(), RegisterLocation(Register(0)))); - AbortIfRegisterCountInvalid(array, formal_parameter_count, register_count); + AbortIfRegisterCountInvalid(array, formal_parameter_count_intptr, + register_count); } - Variable var_index(this, MachineType::PointerRepresentation()); - var_index.Bind(IntPtrConstant(0)); + TVARIABLE(IntPtrT, var_index, IntPtrConstant(0)); // Iterate over array and write values into register file. Also erase the // array contents to not keep them alive artificially. @@ -1689,19 +1693,21 @@ Node* InterpreterAssembler::ImportRegisterFile(Node* array, Goto(&loop); BIND(&loop); { - Node* index = var_index.value(); + TNode<IntPtrT> index = var_index.value(); GotoIfNot(UintPtrLessThan(index, register_count), &done_loop); - Node* array_index = IntPtrAdd(formal_parameter_count, index); - Node* value = LoadFixedArrayElement(array, array_index); + TNode<IntPtrT> array_index = + IntPtrAdd(formal_parameter_count_intptr, index); + TNode<Object> value = LoadFixedArrayElement(array, array_index); - Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); + TNode<IntPtrT> reg_index = + IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); StoreRegister(value, reg_index); StoreFixedArrayElement(array, array_index, LoadRoot(Heap::kStaleRegisterRootIndex)); - var_index.Bind(IntPtrAdd(index, IntPtrConstant(1))); + var_index = IntPtrAdd(index, IntPtrConstant(1)); Goto(&loop); } BIND(&done_loop); diff --git a/deps/v8/src/interpreter/interpreter-assembler.h b/deps/v8/src/interpreter/interpreter-assembler.h index 641d553fd2..036e920837 100644 --- a/deps/v8/src/interpreter/interpreter-assembler.h +++ b/deps/v8/src/interpreter/interpreter-assembler.h @@ -103,11 +103,11 @@ class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler { // - Resume copies only the registers from the generator, the arguments // are copied by the ResumeGenerator trampoline. compiler::Node* ExportParametersAndRegisterFile( - compiler::Node* array, const RegListNodePair& registers, - compiler::Node* formal_parameter_count); - compiler::Node* ImportRegisterFile(compiler::Node* array, + TNode<FixedArray> array, const RegListNodePair& registers, + TNode<Int32T> formal_parameter_count); + compiler::Node* ImportRegisterFile(TNode<FixedArray> array, const RegListNodePair& registers, - compiler::Node* formal_parameter_count); + TNode<Int32T> formal_parameter_count); // Loads from and stores to the interpreter register file. compiler::Node* LoadRegister(Register reg); diff --git a/deps/v8/src/interpreter/interpreter-generator.cc b/deps/v8/src/interpreter/interpreter-generator.cc index 74ebaabcc7..afca2a8a32 100644 --- a/deps/v8/src/interpreter/interpreter-generator.cc +++ b/deps/v8/src/interpreter/interpreter-generator.cc @@ -19,6 +19,7 @@ #include "src/interpreter/interpreter-assembler.h" #include "src/interpreter/interpreter-intrinsics-generator.h" #include "src/objects-inl.h" +#include "src/objects/js-generator.h" #include "src/objects/module.h" namespace v8 { @@ -680,8 +681,8 @@ IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) { BIND(&if_export); { - Node* regular_exports = - LoadObjectField(module, Module::kRegularExportsOffset); + TNode<FixedArray> regular_exports = + CAST(LoadObjectField(module, Module::kRegularExportsOffset)); // The actual array index is (cell_index - 1). Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1)); Node* cell = LoadFixedArrayElement(regular_exports, export_index); @@ -691,8 +692,8 @@ IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) { BIND(&if_import); { - Node* regular_imports = - LoadObjectField(module, Module::kRegularImportsOffset); + TNode<FixedArray> regular_imports = + CAST(LoadObjectField(module, Module::kRegularImportsOffset)); // The actual array index is (-cell_index - 1). Node* import_index = IntPtrSub(IntPtrConstant(-1), cell_index); Node* cell = LoadFixedArrayElement(regular_imports, import_index); @@ -722,8 +723,8 @@ IGNITION_HANDLER(StaModuleVariable, InterpreterAssembler) { BIND(&if_export); { - Node* regular_exports = - LoadObjectField(module, Module::kRegularExportsOffset); + TNode<FixedArray> regular_exports = + CAST(LoadObjectField(module, Module::kRegularExportsOffset)); // The actual array index is (cell_index - 1). Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1)); Node* cell = LoadFixedArrayElement(regular_exports, export_index); @@ -1069,7 +1070,7 @@ IGNITION_HANDLER(BitwiseNot, InterpreterAssembler) { // Number case. BIND(&if_number); TNode<Number> result = - ChangeInt32ToTagged(Signed(Word32Not(var_word32.value()))); + ChangeInt32ToTagged(Signed(Word32BitwiseNot(var_word32.value()))); TNode<Smi> result_type = SelectSmiConstant( TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall, BinaryOperationFeedback::kNumber); @@ -1814,7 +1815,7 @@ IGNITION_HANDLER(TestIn, InterpreterAssembler) { Node* object = GetAccumulator(); Node* context = GetContext(); - SetAccumulator(HasProperty(object, property, context, kHasProperty)); + SetAccumulator(HasProperty(context, object, property, kHasProperty)); Dispatch(); } @@ -2436,6 +2437,26 @@ IGNITION_HANDLER(CreateEmptyObjectLiteral, InterpreterAssembler) { Dispatch(); } +// CloneObject <source_idx> <flags> <feedback_slot> +// +// Allocates a new JSObject with each enumerable own property copied from +// {source}, converting getters into data properties. +IGNITION_HANDLER(CloneObject, InterpreterAssembler) { + Node* source = LoadRegisterAtOperandIndex(0); + Node* bytecode_flags = BytecodeOperandFlag(1); + Node* raw_flags = + DecodeWordFromWord32<CreateObjectLiteralFlags::FlagsBits>(bytecode_flags); + Node* smi_flags = SmiTag(raw_flags); + Node* raw_slot = BytecodeOperandIdx(2); + Node* smi_slot = SmiTag(raw_slot); + Node* feedback_vector = LoadFeedbackVector(); + Node* context = GetContext(); + Node* result = CallBuiltin(Builtins::kCloneObjectIC, context, source, + smi_flags, smi_slot, feedback_vector); + SetAccumulator(result); + Dispatch(); +} + // GetTemplateObject <descriptor_idx> <literal_idx> // // Creates the template to pass for tagged templates and returns it in the @@ -2911,7 +2932,7 @@ IGNITION_HANDLER(ForInNext, InterpreterAssembler) { Node* feedback_vector = LoadFeedbackVector(); // Load the next key from the enumeration array. - Node* key = LoadFixedArrayElement(cache_array, index, 0, + Node* key = LoadFixedArrayElement(CAST(cache_array), index, 0, CodeStubAssembler::SMI_PARAMETERS); // Check if we can use the for-in fast path potentially using the enum cache. @@ -3004,8 +3025,8 @@ IGNITION_HANDLER(Illegal, InterpreterAssembler) { // in the accumulator. IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) { Node* generator = LoadRegisterAtOperandIndex(0); - Node* array = LoadObjectField( - generator, JSGeneratorObject::kParametersAndRegistersOffset); + TNode<FixedArray> array = CAST(LoadObjectField( + generator, JSGeneratorObject::kParametersAndRegistersOffset)); Node* closure = LoadRegister(Register::function_closure()); Node* context = GetContext(); RegListNodePair registers = GetRegisterListAtOperandIndex(1); @@ -3013,9 +3034,9 @@ IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) { Node* shared = LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset); - Node* formal_parameter_count = + TNode<Int32T> formal_parameter_count = UncheckedCast<Int32T>( LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset, - MachineType::Uint16()); + MachineType::Uint16())); ExportParametersAndRegisterFile(array, registers, formal_parameter_count); StoreObjectField(generator, JSGeneratorObject::kContextOffset, context); @@ -3087,13 +3108,13 @@ IGNITION_HANDLER(ResumeGenerator, InterpreterAssembler) { Node* shared = LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset); - Node* formal_parameter_count = + TNode<Int32T> formal_parameter_count = UncheckedCast<Int32T>( LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset, - MachineType::Uint16()); + MachineType::Uint16())); ImportRegisterFile( - LoadObjectField(generator, - JSGeneratorObject::kParametersAndRegistersOffset), + CAST(LoadObjectField(generator, + JSGeneratorObject::kParametersAndRegistersOffset)), registers, formal_parameter_count); // Return the generator's input_or_debug_pos in the accumulator. @@ -3106,14 +3127,16 @@ IGNITION_HANDLER(ResumeGenerator, InterpreterAssembler) { } // namespace Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode, - OperandScale operand_scale) { + OperandScale operand_scale, + int builtin_index) { Zone zone(isolate->allocator(), ZONE_NAME); compiler::CodeAssemblerState state( isolate, &zone, InterpreterDispatchDescriptor{}, Code::BYTECODE_HANDLER, Bytecodes::ToString(bytecode), FLAG_untrusted_code_mitigations ? PoisoningMitigationLevel::kPoisonCriticalOnly - : PoisoningMitigationLevel::kDontPoison); + : PoisoningMitigationLevel::kDontPoison, + 0, builtin_index); switch (bytecode) { #define CALL_GENERATOR(Name, ...) \ diff --git a/deps/v8/src/interpreter/interpreter-generator.h b/deps/v8/src/interpreter/interpreter-generator.h index 3dbdcf829d..bc3793a45f 100644 --- a/deps/v8/src/interpreter/interpreter-generator.h +++ b/deps/v8/src/interpreter/interpreter-generator.h @@ -13,7 +13,8 @@ namespace internal { namespace interpreter { extern Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode, - OperandScale operand_scale); + OperandScale operand_scale, + int builtin_index); extern Handle<Code> GenerateDeserializeLazyHandler(Isolate* isolate, OperandScale operand_scale); diff --git a/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc b/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc index 62785d7904..55e554e2e0 100644 --- a/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc +++ b/deps/v8/src/interpreter/interpreter-intrinsics-generator.cc @@ -13,6 +13,7 @@ #include "src/interpreter/interpreter-assembler.h" #include "src/interpreter/interpreter-intrinsics.h" #include "src/objects-inl.h" +#include "src/objects/js-generator.h" #include "src/objects/module.h" namespace v8 { @@ -170,18 +171,6 @@ Node* IntrinsicsGenerator::IsTypedArray( return IsInstanceType(input, JS_TYPED_ARRAY_TYPE); } -Node* IntrinsicsGenerator::IsJSWeakMap( - const InterpreterAssembler::RegListNodePair& args, Node* context) { - Node* input = __ LoadRegisterFromRegisterList(args, 0); - return IsInstanceType(input, JS_WEAK_MAP_TYPE); -} - -Node* IntrinsicsGenerator::IsJSWeakSet( - const InterpreterAssembler::RegListNodePair& args, Node* context) { - Node* input = __ LoadRegisterFromRegisterList(args, 0); - return IsInstanceType(input, JS_WEAK_SET_TYPE); -} - Node* IntrinsicsGenerator::IsSmi( const InterpreterAssembler::RegListNodePair& args, Node* context) { Node* input = __ LoadRegisterFromRegisterList(args, 0); @@ -223,6 +212,12 @@ 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( diff --git a/deps/v8/src/interpreter/interpreter-intrinsics.h b/deps/v8/src/interpreter/interpreter-intrinsics.h index 570caca072..04f662f0df 100644 --- a/deps/v8/src/interpreter/interpreter-intrinsics.h +++ b/deps/v8/src/interpreter/interpreter-intrinsics.h @@ -26,11 +26,10 @@ namespace interpreter { 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(IsJSWeakMap, is_js_weak_map, 1) \ - V(IsJSWeakSet, is_js_weak_set, 1) \ V(IsSmi, is_smi, 1) \ V(IsTypedArray, is_typed_array, 1) \ V(RejectPromise, reject_promise, 3) \ diff --git a/deps/v8/src/interpreter/setup-interpreter-internal.cc b/deps/v8/src/interpreter/setup-interpreter-internal.cc index 2e0a7d8ca5..8f2b565c00 100644 --- a/deps/v8/src/interpreter/setup-interpreter-internal.cc +++ b/deps/v8/src/interpreter/setup-interpreter-internal.cc @@ -80,7 +80,11 @@ void SetupInterpreter::InstallBytecodeHandler(Isolate* isolate, if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return; size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale); - Handle<Code> code = GenerateBytecodeHandler(isolate, 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); |