summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/bytecode-generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-generator.cc')
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.cc169
1 files changed, 134 insertions, 35 deletions
diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc
index 706580ac14..d3b27b4375 100644
--- a/deps/v8/src/interpreter/bytecode-generator.cc
+++ b/deps/v8/src/interpreter/bytecode-generator.cc
@@ -915,6 +915,45 @@ class BytecodeGenerator::IteratorRecord final {
Register next_;
};
+namespace {
+
+// A map from property names to getter/setter pairs allocated in the zone that
+// also provides a way of accessing the pairs in the order they were first
+// added so that the generated bytecode is always the same.
+class AccessorTable
+ : public base::TemplateHashMap<Literal, ObjectLiteral::Accessors,
+ bool (*)(void*, void*),
+ ZoneAllocationPolicy> {
+ public:
+ explicit AccessorTable(Zone* zone)
+ : base::TemplateHashMap<Literal, ObjectLiteral::Accessors,
+ bool (*)(void*, void*), ZoneAllocationPolicy>(
+ Literal::Match, ZoneAllocationPolicy(zone)),
+ zone_(zone) {}
+
+ Iterator lookup(Literal* literal) {
+ Iterator it = find(literal, true, ZoneAllocationPolicy(zone_));
+ if (it->second == nullptr) {
+ it->second = new (zone_) ObjectLiteral::Accessors();
+ ordered_accessors_.push_back({literal, it->second});
+ }
+ return it;
+ }
+
+ const std::vector<std::pair<Literal*, ObjectLiteral::Accessors*>>&
+ ordered_accessors() {
+ return ordered_accessors_;
+ }
+
+ private:
+ std::vector<std::pair<Literal*, ObjectLiteral::Accessors*>>
+ ordered_accessors_;
+
+ Zone* zone_;
+};
+
+} // namespace
+
#ifdef DEBUG
static bool IsInEagerLiterals(
@@ -1354,7 +1393,8 @@ void BytecodeGenerator::VisitModuleNamespaceImports() {
RegisterAllocationScope register_scope(this);
Register module_request = register_allocator()->NewRegister();
- ModuleDescriptor* descriptor = closure_scope()->AsModuleScope()->module();
+ SourceTextModuleDescriptor* descriptor =
+ closure_scope()->AsModuleScope()->module();
for (auto entry : descriptor->namespace_imports()) {
builder()
->LoadLiteral(Smi::FromInt(entry->module_request))
@@ -2201,6 +2241,19 @@ void BytecodeGenerator::VisitInitializeClassMembersStatement(
}
}
+void BytecodeGenerator::BuildThrowPrivateMethodWriteError(
+ const AstRawString* name) {
+ RegisterAllocationScope register_scope(this);
+ RegisterList args = register_allocator()->NewRegisterList(2);
+ builder()
+ ->LoadLiteral(Smi::FromEnum(MessageTemplate::kInvalidPrivateMethodWrite))
+ .StoreAccumulatorInRegister(args[0])
+ .LoadLiteral(name)
+ .StoreAccumulatorInRegister(args[1])
+ .CallRuntime(Runtime::kNewTypeError, args)
+ .Throw();
+}
+
void BytecodeGenerator::BuildPrivateBrandInitialization(Register receiver) {
RegisterList brand_args = register_allocator()->NewRegisterList(2);
Variable* brand = info()->scope()->outer_scope()->AsClassScope()->brand();
@@ -2366,13 +2419,6 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
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);
@@ -2473,14 +2519,13 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// Define accessors, using only a single call to the runtime for each pair of
// corresponding getters and setters.
- for (AccessorTable::Iterator it = accessor_table.begin();
- it != accessor_table.end(); ++it) {
+ for (auto accessors : accessor_table.ordered_accessors()) {
RegisterAllocationScope inner_register_scope(this);
RegisterList args = register_allocator()->NewRegisterList(5);
builder()->MoveRegister(literal, args[0]);
- VisitForRegisterValue(it->first, args[1]);
- VisitObjectLiteralAccessor(literal, it->second->getter, args[2]);
- VisitObjectLiteralAccessor(literal, it->second->setter, args[3]);
+ VisitForRegisterValue(accessors.first, args[1]);
+ VisitObjectLiteralAccessor(literal, accessors.second->getter, args[2]);
+ VisitObjectLiteralAccessor(literal, accessors.second->setter, args[3]);
builder()
->LoadLiteral(Smi::FromInt(NONE))
.StoreAccumulatorInRegister(args[4])
@@ -3156,6 +3201,13 @@ BytecodeGenerator::AssignmentLhsData::NamedSuperProperty(
}
// static
BytecodeGenerator::AssignmentLhsData
+BytecodeGenerator::AssignmentLhsData::PrivateMethod(Register object,
+ const AstRawString* name) {
+ return AssignmentLhsData(PRIVATE_METHOD, nullptr, RegisterList(), object,
+ Register(), nullptr, name);
+}
+// static
+BytecodeGenerator::AssignmentLhsData
BytecodeGenerator::AssignmentLhsData::KeyedSuperProperty(
RegisterList super_property_args) {
return AssignmentLhsData(KEYED_SUPER_PROPERTY, nullptr, super_property_args,
@@ -3185,6 +3237,13 @@ BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
Register key = VisitForRegisterValue(property->key());
return AssignmentLhsData::KeyedProperty(object, key);
}
+ case PRIVATE_METHOD: {
+ DCHECK(!property->IsSuperAccess());
+ AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
+ Register object = VisitForRegisterValue(property->obj());
+ const AstRawString* name = property->key()->AsVariableProxy()->raw_name();
+ return AssignmentLhsData::PrivateMethod(object, name);
+ }
case NAMED_SUPER_PROPERTY: {
AccumulatorPreservingScope scope(this, accumulator_preserving_mode);
RegisterList super_property_args =
@@ -3219,15 +3278,16 @@ BytecodeGenerator::AssignmentLhsData BytecodeGenerator::PrepareAssignmentLhs(
// Build the iteration finalizer called in the finally block of an iteration
// protocol execution. This closes the iterator if needed, and suppresses any
-// exception it throws if necessary.
+// exception it throws if necessary, including the exception when the return
+// method is not callable.
//
// In pseudo-code, this builds:
//
// if (!done) {
// let method = iterator.return
// if (method !== null && method !== undefined) {
-// if (typeof(method) !== "function") throw TypeError
// try {
+// if (typeof(method) !== "function") throw TypeError
// let return_val = method.call(iterator)
// if (!%IsObject(return_val)) throw TypeError
// } catch (e) {
@@ -3259,33 +3319,35 @@ void BytecodeGenerator::BuildFinalizeIteration(
.JumpIfUndefined(iterator_is_done.New())
.JumpIfNull(iterator_is_done.New());
- // if (typeof(method) !== "function") throw TypeError
- BytecodeLabel if_callable;
- builder()
- ->CompareTypeOf(TestTypeOfFlags::LiteralFlag::kFunction)
- .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &if_callable);
- {
- // throw %NewTypeError(kReturnMethodNotCallable)
- RegisterAllocationScope register_scope(this);
- RegisterList new_type_error_args = register_allocator()->NewRegisterList(2);
- builder()
- ->LoadLiteral(Smi::FromEnum(MessageTemplate::kReturnMethodNotCallable))
- .StoreAccumulatorInRegister(new_type_error_args[0])
- .LoadLiteral(ast_string_constants()->empty_string())
- .StoreAccumulatorInRegister(new_type_error_args[1])
- .CallRuntime(Runtime::kNewTypeError, new_type_error_args)
- .Throw();
- }
- builder()->Bind(&if_callable);
-
{
RegisterAllocationScope register_scope(this);
BuildTryCatch(
// try {
+ // if (typeof(method) !== "function") throw TypeError
// let return_val = method.call(iterator)
// if (!%IsObject(return_val)) throw TypeError
// }
[&]() {
+ BytecodeLabel if_callable;
+ builder()
+ ->CompareTypeOf(TestTypeOfFlags::LiteralFlag::kFunction)
+ .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &if_callable);
+ {
+ // throw %NewTypeError(kReturnMethodNotCallable)
+ RegisterAllocationScope register_scope(this);
+ RegisterList new_type_error_args =
+ register_allocator()->NewRegisterList(2);
+ builder()
+ ->LoadLiteral(
+ Smi::FromEnum(MessageTemplate::kReturnMethodNotCallable))
+ .StoreAccumulatorInRegister(new_type_error_args[0])
+ .LoadLiteral(ast_string_constants()->empty_string())
+ .StoreAccumulatorInRegister(new_type_error_args[1])
+ .CallRuntime(Runtime::kNewTypeError, new_type_error_args)
+ .Throw();
+ }
+ builder()->Bind(&if_callable);
+
RegisterList args(iterator.object());
builder()->CallProperty(
method, args, feedback_index(feedback_spec()->AddCallICSlot()));
@@ -3736,6 +3798,10 @@ void BytecodeGenerator::BuildAssignment(
lhs_data.super_property_args());
break;
}
+ case PRIVATE_METHOD: {
+ BuildThrowPrivateMethodWriteError(lhs_data.name());
+ break;
+ }
}
}
@@ -3781,6 +3847,10 @@ void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
lhs_data.super_property_args().Truncate(3));
break;
}
+ case PRIVATE_METHOD: {
+ BuildThrowPrivateMethodWriteError(lhs_data.name());
+ break;
+ }
}
BinaryOperation* binop = expr->AsCompoundAssignment()->binary_operation();
FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
@@ -4238,6 +4308,23 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
case KEYED_SUPER_PROPERTY:
VisitKeyedSuperPropertyLoad(property, Register::invalid_value());
break;
+ case PRIVATE_METHOD: {
+ Variable* private_name = property->key()->AsVariableProxy()->var();
+
+ // Perform the brand check.
+ DCHECK(private_name->requires_brand_check());
+ ClassScope* scope = private_name->scope()->AsClassScope();
+ Variable* brand = scope->brand();
+ BuildVariableLoadForAccumulatorValue(brand, HoleCheckMode::kElided);
+ builder()->SetExpressionPosition(property);
+ builder()->LoadKeyedProperty(
+ obj, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
+
+ // In the case of private methods, property->key() is the function to be
+ // loaded (stored in a context slot), so load this directly.
+ VisitForAccumulatorValue(property->key());
+ break;
+ }
}
}
@@ -4342,7 +4429,8 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// the semantics of the underlying call type.
switch (call_type) {
case Call::NAMED_PROPERTY_CALL:
- case Call::KEYED_PROPERTY_CALL: {
+ case Call::KEYED_PROPERTY_CALL:
+ case Call::PRIVATE_CALL: {
Property* property = callee_expr->AsProperty();
VisitAndPushIntoRegisterList(property->obj(), &args);
VisitPropertyLoadForRegister(args.last_register(), property, callee);
@@ -4678,6 +4766,7 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* unary) {
// Delete of an object property is allowed both in sloppy
// and strict modes.
Property* property = expr->AsProperty();
+ DCHECK(!property->IsPrivateReference());
Register object = VisitForRegisterValue(property->obj());
VisitForAccumulatorValue(property->key());
builder()->Delete(object, language_mode());
@@ -4785,6 +4874,11 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args);
break;
}
+ case PRIVATE_METHOD: {
+ BuildThrowPrivateMethodWriteError(
+ property->key()->AsVariableProxy()->raw_name());
+ break;
+ }
}
// Save result for postfix expressions.
@@ -4851,6 +4945,11 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
.CallRuntime(Runtime::kStoreKeyedToSuper, super_property_args);
break;
}
+ case PRIVATE_METHOD: {
+ BuildThrowPrivateMethodWriteError(
+ property->key()->AsVariableProxy()->raw_name());
+ break;
+ }
}
// Restore old value for postfix expressions.