summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/interpreter')
-rw-r--r--deps/v8/src/interpreter/bytecode-array-builder.cc7
-rw-r--r--deps/v8/src/interpreter/bytecode-array-builder.h2
-rw-r--r--deps/v8/src/interpreter/bytecode-array-writer.cc2
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.cc198
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.h11
-rw-r--r--deps/v8/src/interpreter/bytecodes.h2
-rw-r--r--deps/v8/src/interpreter/constant-array-builder.h1
-rw-r--r--deps/v8/src/interpreter/interpreter-assembler.cc50
-rw-r--r--deps/v8/src/interpreter/interpreter-assembler.h8
-rw-r--r--deps/v8/src/interpreter/interpreter-generator.cc61
-rw-r--r--deps/v8/src/interpreter/interpreter-generator.h3
-rw-r--r--deps/v8/src/interpreter/interpreter-intrinsics-generator.cc19
-rw-r--r--deps/v8/src/interpreter/interpreter-intrinsics.h3
-rw-r--r--deps/v8/src/interpreter/setup-interpreter-internal.cc6
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);