[interpreter] Support for ES6 super keyword.
Adds support for ES6 super keyword and performing loads, stores, and calls to super class members. Implements SetHomeObject and enables ThisFunctionVariable. BUG=v8:4280,v8:4682 LOG=N Review URL: https://codereview.chromium.org/1689573004 Cr-Commit-Position: refs/heads/master@{#33977}
This commit is contained in:
parent
f0561ac5d9
commit
e768bcca24
@ -1136,33 +1136,34 @@ void BytecodeGraphBuilder::VisitCallRuntimeForPairWide() {
|
||||
BuildCallRuntimeForPair();
|
||||
}
|
||||
|
||||
|
||||
Node* BytecodeGraphBuilder::ProcessCallNewArguments(
|
||||
const Operator* call_new_op, interpreter::Register callee,
|
||||
const Operator* call_new_op, Node* callee, Node* new_target,
|
||||
interpreter::Register first_arg, size_t arity) {
|
||||
Node** all = info()->zone()->NewArray<Node*>(arity);
|
||||
all[0] = environment()->LookupRegister(callee);
|
||||
all[0] = new_target;
|
||||
int first_arg_index = first_arg.index();
|
||||
for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
|
||||
all[i] = environment()->LookupRegister(
|
||||
interpreter::Register(first_arg_index + i - 1));
|
||||
}
|
||||
// Original constructor is the same as the callee.
|
||||
all[arity - 1] = environment()->LookupRegister(callee);
|
||||
all[arity - 1] = callee;
|
||||
Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
|
||||
return value;
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::BuildCallConstruct() {
|
||||
FrameStateBeforeAndAfter states(this);
|
||||
interpreter::Register callee = bytecode_iterator().GetRegisterOperand(0);
|
||||
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
|
||||
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
|
||||
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
|
||||
|
||||
Node* new_target = environment()->LookupAccumulator();
|
||||
Node* callee = environment()->LookupRegister(callee_reg);
|
||||
// TODO(turbofan): Pass the feedback here.
|
||||
const Operator* call = javascript()->CallConstruct(
|
||||
static_cast<int>(arg_count) + 2, VectorSlotPair());
|
||||
Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2);
|
||||
Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg,
|
||||
arg_count + 2);
|
||||
environment()->BindAccumulator(value, &states);
|
||||
}
|
||||
|
||||
|
@ -103,8 +103,8 @@ class BytecodeGraphBuilder {
|
||||
|
||||
Node* ProcessCallArguments(const Operator* call_op, Node* callee,
|
||||
interpreter::Register receiver, size_t arity);
|
||||
Node* ProcessCallNewArguments(const Operator* call_new_op,
|
||||
interpreter::Register callee,
|
||||
Node* ProcessCallNewArguments(const Operator* call_new_op, Node* callee,
|
||||
Node* new_target,
|
||||
interpreter::Register first_arg, size_t arity);
|
||||
Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
|
||||
interpreter::Register first_arg,
|
||||
|
@ -484,9 +484,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
|
||||
Register object, const Handle<String> name, int feedback_slot,
|
||||
Register object, const Handle<Name> name, int feedback_slot,
|
||||
LanguageMode language_mode) {
|
||||
Bytecode bytecode = BytecodeForLoadIC(language_mode);
|
||||
size_t name_index = GetConstantPoolEntry(name);
|
||||
@ -520,9 +519,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
|
||||
Register object, const Handle<String> name, int feedback_slot,
|
||||
Register object, const Handle<Name> name, int feedback_slot,
|
||||
LanguageMode language_mode) {
|
||||
Bytecode bytecode = BytecodeForStoreIC(language_mode);
|
||||
size_t name_index = GetConstantPoolEntry(name);
|
||||
@ -1107,7 +1105,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
|
||||
Register first_arg,
|
||||
size_t arg_count) {
|
||||
|
@ -114,7 +114,7 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
|
||||
|
||||
// Named load property.
|
||||
BytecodeArrayBuilder& LoadNamedProperty(Register object,
|
||||
const Handle<String> name,
|
||||
const Handle<Name> name,
|
||||
int feedback_slot,
|
||||
LanguageMode language_mode);
|
||||
// Keyed load property. The key should be in the accumulator.
|
||||
@ -123,7 +123,7 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
|
||||
|
||||
// Store properties. The value to be stored should be in the accumulator.
|
||||
BytecodeArrayBuilder& StoreNamedProperty(Register object,
|
||||
const Handle<String> name,
|
||||
const Handle<Name> name,
|
||||
int feedback_slot,
|
||||
LanguageMode language_mode);
|
||||
BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
|
||||
@ -167,9 +167,10 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
|
||||
BytecodeArrayBuilder& Call(Register callable, Register receiver_args,
|
||||
size_t receiver_arg_count, int feedback_slot);
|
||||
|
||||
// Call the new operator. The |constructor| register is followed by
|
||||
// |arg_count| consecutive registers containing arguments to be
|
||||
// applied to the constructor.
|
||||
// Call the new operator. The accumulator holds the |new_target|.
|
||||
// The |constructor| is in a register followed by |arg_count|
|
||||
// consecutive arguments starting at |first_arg| for the constuctor
|
||||
// invocation.
|
||||
BytecodeArrayBuilder& New(Register constructor, Register first_arg,
|
||||
size_t arg_count);
|
||||
|
||||
|
@ -418,6 +418,11 @@ class BytecodeGenerator::RegisterAllocationScope {
|
||||
return allocator_.NextConsecutiveRegister();
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void PrepareAndInitializeConsecutiveAllocations(Register (®isters)[N]) {
|
||||
return allocator_.PrepareAndInitializeConsecutiveAllocations(registers, N);
|
||||
}
|
||||
|
||||
bool RegisterIsAllocatedInThisScope(Register reg) const {
|
||||
return allocator_.RegisterIsAllocatedInThisScope(reg);
|
||||
}
|
||||
@ -543,6 +548,26 @@ class BytecodeGenerator::RegisterResultScope final
|
||||
Register result_register_;
|
||||
};
|
||||
|
||||
// Class for holding arguments for runtime calls relating to super
|
||||
// properties.
|
||||
class BytecodeGenerator::SuperPropertyArguments final {
|
||||
public:
|
||||
SuperPropertyArguments() {}
|
||||
|
||||
Register (®isters())[4] { return args_; }
|
||||
Register receiver() const { return args_[0]; }
|
||||
Register home_object() const { return args_[1]; }
|
||||
Register name_or_key() const { return args_[2]; }
|
||||
Register store_value() const { return args_[3]; }
|
||||
Register language_mode() const { return args_[3]; }
|
||||
size_t count() const { return arraysize(args_); }
|
||||
|
||||
private:
|
||||
Register args_[4];
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SuperPropertyArguments);
|
||||
};
|
||||
|
||||
BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
|
||||
: isolate_(isolate),
|
||||
zone_(zone),
|
||||
@ -559,7 +584,6 @@ BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
|
||||
InitializeAstVisitor(isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
|
||||
set_info(info);
|
||||
set_scope(info->scope());
|
||||
@ -1050,9 +1074,30 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr,
|
||||
language_mode());
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
SuperPropertyArguments super_args;
|
||||
Register value = register_allocator()->NewRegister();
|
||||
builder()->StoreAccumulatorInRegister(value);
|
||||
PrepareNamedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(),
|
||||
property->key()->AsLiteral()->AsPropertyName(), &super_args);
|
||||
builder()->LoadAccumulatorWithRegister(value);
|
||||
BuildNamedSuperPropertyStore(&super_args);
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
SuperPropertyArguments super_args;
|
||||
Register value = register_allocator()->NewRegister();
|
||||
builder()->StoreAccumulatorInRegister(value);
|
||||
PrepareKeyedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(), property->key(),
|
||||
&super_args);
|
||||
builder()->LoadAccumulatorWithRegister(value);
|
||||
BuildKeyedSuperPropertyStore(&super_args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1495,9 +1540,19 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
if (literal_key->value()->IsInternalizedString()) {
|
||||
if (property->emit_store()) {
|
||||
VisitForAccumulatorValue(property->value());
|
||||
builder()->StoreNamedProperty(
|
||||
literal, literal_key->AsPropertyName(),
|
||||
feedback_index(property->GetSlot(0)), language_mode());
|
||||
if (FunctionLiteral::NeedsHomeObject(property->value())) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
Register value = register_allocator()->NewRegister();
|
||||
builder()->StoreAccumulatorInRegister(value);
|
||||
builder()->StoreNamedProperty(
|
||||
literal, literal_key->AsPropertyName(),
|
||||
feedback_index(property->GetSlot(0)), language_mode());
|
||||
VisitSetHomeObject(value, literal, property, 1);
|
||||
} else {
|
||||
builder()->StoreNamedProperty(
|
||||
literal, literal_key->AsPropertyName(),
|
||||
feedback_index(property->GetSlot(0)), language_mode());
|
||||
}
|
||||
} else {
|
||||
VisitForEffect(property->value());
|
||||
}
|
||||
@ -1781,6 +1836,72 @@ Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
|
||||
return register_scope.ResultRegister();
|
||||
}
|
||||
|
||||
void BytecodeGenerator::PrepareNamedSuperPropertyArguments(
|
||||
SuperPropertyReference* super_property, Handle<Name> name,
|
||||
SuperPropertyArguments* super_args) {
|
||||
register_allocator()->PrepareAndInitializeConsecutiveAllocations(
|
||||
super_args->registers());
|
||||
|
||||
VisitForAccumulatorValue(super_property->this_var());
|
||||
builder()->StoreAccumulatorInRegister(super_args->receiver());
|
||||
VisitForAccumulatorValue(super_property->home_object());
|
||||
builder()->StoreAccumulatorInRegister(super_args->home_object());
|
||||
builder()->LoadLiteral(name).StoreAccumulatorInRegister(
|
||||
super_args->name_or_key());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::PrepareKeyedSuperPropertyArguments(
|
||||
SuperPropertyReference* super_property, Expression* key,
|
||||
SuperPropertyArguments* super_args) {
|
||||
register_allocator()->PrepareAndInitializeConsecutiveAllocations(
|
||||
super_args->registers());
|
||||
|
||||
VisitForAccumulatorValue(super_property->this_var());
|
||||
builder()->StoreAccumulatorInRegister(super_args->receiver());
|
||||
VisitForAccumulatorValue(super_property->home_object());
|
||||
builder()->StoreAccumulatorInRegister(super_args->home_object());
|
||||
VisitForAccumulatorValue(key);
|
||||
builder()->StoreAccumulatorInRegister(super_args->name_or_key());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildNamedSuperPropertyLoad(
|
||||
SuperPropertyArguments* super_args) {
|
||||
builder()
|
||||
->LoadLiteral(Smi::FromInt(static_cast<int>(language_mode())))
|
||||
.StoreAccumulatorInRegister(super_args->language_mode());
|
||||
builder()->CallRuntime(Runtime::kLoadFromSuper, super_args->receiver(),
|
||||
super_args->count());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildKeyedSuperPropertyLoad(
|
||||
SuperPropertyArguments* super_args) {
|
||||
builder()
|
||||
->LoadLiteral(Smi::FromInt(static_cast<int>(language_mode())))
|
||||
.StoreAccumulatorInRegister(super_args->language_mode());
|
||||
builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, super_args->receiver(),
|
||||
super_args->count());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildNamedSuperPropertyStore(
|
||||
SuperPropertyArguments* super_args) {
|
||||
builder()->StoreAccumulatorInRegister(super_args->store_value());
|
||||
Runtime::FunctionId function_id = is_strict(language_mode())
|
||||
? Runtime::kStoreToSuper_Strict
|
||||
: Runtime::kStoreToSuper_Sloppy;
|
||||
builder()->CallRuntime(function_id, super_args->receiver(),
|
||||
super_args->count());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildKeyedSuperPropertyStore(
|
||||
SuperPropertyArguments* super_args) {
|
||||
builder()->StoreAccumulatorInRegister(super_args->store_value());
|
||||
Runtime::FunctionId function_id = is_strict(language_mode())
|
||||
? Runtime::kStoreKeyedToSuper_Strict
|
||||
: Runtime::kStoreKeyedToSuper_Sloppy;
|
||||
builder()->CallRuntime(function_id, super_args->receiver(),
|
||||
super_args->count());
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
Register name_reg = register_allocator()->NewRegister();
|
||||
@ -1836,7 +1957,7 @@ void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
|
||||
// Perform an initialization check for 'this'. 'this' variable is the
|
||||
// only variable able to trigger bind operations outside the TDZ
|
||||
// via 'super' calls.
|
||||
BuildThrowIfHole(variable->name());
|
||||
BuildThrowIfNotHole(variable->name());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1988,8 +2109,9 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
|
||||
Register object, key;
|
||||
SuperPropertyArguments super_args;
|
||||
Handle<String> name;
|
||||
|
||||
// Left-hand side can only be a property, a global or a variable slot.
|
||||
@ -2019,9 +2141,18 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
PrepareNamedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(),
|
||||
property->key()->AsLiteral()->AsPropertyName(), &super_args);
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
PrepareKeyedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(), property->key(),
|
||||
&super_args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the value and potentially handle compound assignments by loading
|
||||
@ -2054,10 +2185,18 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
.StoreAccumulatorInRegister(old_value);
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
old_value = register_allocator()->NewRegister();
|
||||
BuildNamedSuperPropertyLoad(&super_args);
|
||||
builder()->StoreAccumulatorInRegister(old_value);
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
old_value = register_allocator()->NewRegister();
|
||||
BuildKeyedSuperPropertyLoad(&super_args);
|
||||
builder()->StoreAccumulatorInRegister(old_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
builder()->BinaryOperation(expr->binary_op(), old_value,
|
||||
@ -2084,9 +2223,14 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
builder()->StoreKeyedProperty(object, key, feedback_index(slot),
|
||||
language_mode());
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
BuildNamedSuperPropertyStore(&super_args);
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
BuildKeyedSuperPropertyStore(&super_args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
@ -2124,25 +2268,57 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
|
||||
break;
|
||||
}
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
|
||||
Property* expr) {
|
||||
AccumulatorResultScope result_scope(this);
|
||||
VisitPropertyLoad(obj, expr);
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitProperty(Property* expr) {
|
||||
Register obj = VisitForRegisterValue(expr->obj());
|
||||
VisitPropertyLoad(obj, expr);
|
||||
void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
|
||||
Register opt_receiver_out) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
SuperPropertyArguments super_args;
|
||||
PrepareNamedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(),
|
||||
property->key()->AsLiteral()->AsPropertyName(), &super_args);
|
||||
if (opt_receiver_out.is_valid()) {
|
||||
builder()->MoveRegister(super_args.receiver(), opt_receiver_out);
|
||||
}
|
||||
BuildNamedSuperPropertyLoad(&super_args);
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
|
||||
Register opt_receiver_out) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
SuperPropertyArguments super_args;
|
||||
PrepareKeyedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(), property->key(),
|
||||
&super_args);
|
||||
if (opt_receiver_out.is_valid()) {
|
||||
builder()->MoveRegister(super_args.receiver(), opt_receiver_out);
|
||||
}
|
||||
BuildKeyedSuperPropertyLoad(&super_args);
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitProperty(Property* expr) {
|
||||
LhsKind property_kind = Property::GetAssignType(expr);
|
||||
if (property_kind != NAMED_SUPER_PROPERTY &&
|
||||
property_kind != KEYED_SUPER_PROPERTY) {
|
||||
Register obj = VisitForRegisterValue(expr->obj());
|
||||
VisitPropertyLoad(obj, expr);
|
||||
} else {
|
||||
VisitPropertyLoad(Register::invalid_value(), expr);
|
||||
}
|
||||
}
|
||||
|
||||
Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
|
||||
if (args->length() == 0) {
|
||||
@ -2176,11 +2352,14 @@ Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
|
||||
return first_arg;
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitCall(Call* expr) {
|
||||
Expression* callee_expr = expr->expression();
|
||||
Call::CallType call_type = expr->GetCallType(isolate());
|
||||
|
||||
if (call_type == Call::SUPER_CALL) {
|
||||
return VisitCallSuper(expr);
|
||||
}
|
||||
|
||||
// Prepare the callee and the receiver to the function call. This depends on
|
||||
// the semantics of the underlying call type.
|
||||
|
||||
@ -2238,10 +2417,21 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
||||
builder()->StoreAccumulatorInRegister(callee);
|
||||
break;
|
||||
}
|
||||
case Call::NAMED_SUPER_PROPERTY_CALL:
|
||||
case Call::KEYED_SUPER_PROPERTY_CALL:
|
||||
case Call::NAMED_SUPER_PROPERTY_CALL: {
|
||||
Property* property = callee_expr->AsProperty();
|
||||
VisitNamedSuperPropertyLoad(property, receiver);
|
||||
builder()->StoreAccumulatorInRegister(callee);
|
||||
break;
|
||||
}
|
||||
case Call::KEYED_SUPER_PROPERTY_CALL: {
|
||||
Property* property = callee_expr->AsProperty();
|
||||
VisitKeyedSuperPropertyLoad(property, receiver);
|
||||
builder()->StoreAccumulatorInRegister(callee);
|
||||
break;
|
||||
}
|
||||
case Call::SUPER_CALL:
|
||||
UNIMPLEMENTED();
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
// Evaluate all arguments to the function call and store in sequential
|
||||
@ -2285,6 +2475,32 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitCallSuper(Call* expr) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
SuperCallReference* super = expr->expression()->AsSuperCallReference();
|
||||
|
||||
// Prepare the constructor to the super call.
|
||||
Register this_function = register_allocator()->NewRegister();
|
||||
VisitForAccumulatorValue(super->this_function_var());
|
||||
builder()
|
||||
->StoreAccumulatorInRegister(this_function)
|
||||
.CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1);
|
||||
|
||||
Register constructor = this_function; // Re-use dead this_function register.
|
||||
builder()->StoreAccumulatorInRegister(constructor);
|
||||
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Register first_arg = VisitArguments(args);
|
||||
|
||||
// The new target is loaded into the accumulator from the
|
||||
// {new.target} variable.
|
||||
VisitForAccumulatorValue(super->new_target_var());
|
||||
|
||||
// Call construct.
|
||||
builder()->SetExpressionPosition(expr);
|
||||
builder()->New(constructor, first_arg, args->length());
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
Register constructor = register_allocator()->NewRegister();
|
||||
@ -2293,8 +2509,13 @@ void BytecodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Register first_arg = VisitArguments(args);
|
||||
|
||||
builder()->SetExpressionPosition(expr);
|
||||
builder()->New(constructor, first_arg, args->length());
|
||||
// The accumulator holds new target which is the same as the
|
||||
// constructor for CallNew.
|
||||
builder()
|
||||
->LoadAccumulatorWithRegister(constructor)
|
||||
.New(constructor, first_arg, args->length());
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
@ -2448,7 +2669,8 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
bool is_postfix = expr->is_postfix();
|
||||
|
||||
// Evaluate LHS expression and get old value.
|
||||
Register obj, key, old_value;
|
||||
Register object, key, old_value;
|
||||
SuperPropertyArguments super_args;
|
||||
Handle<String> name;
|
||||
switch (assign_type) {
|
||||
case VARIABLE: {
|
||||
@ -2459,26 +2681,37 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
case NAMED_PROPERTY: {
|
||||
FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
|
||||
obj = VisitForRegisterValue(property->obj());
|
||||
object = VisitForRegisterValue(property->obj());
|
||||
name = property->key()->AsLiteral()->AsPropertyName();
|
||||
builder()->LoadNamedProperty(obj, name, feedback_index(slot),
|
||||
builder()->LoadNamedProperty(object, name, feedback_index(slot),
|
||||
language_mode());
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
|
||||
obj = VisitForRegisterValue(property->obj());
|
||||
object = VisitForRegisterValue(property->obj());
|
||||
// Use visit for accumulator here since we need the key in the accumulator
|
||||
// for the LoadKeyedProperty.
|
||||
key = register_allocator()->NewRegister();
|
||||
VisitForAccumulatorValue(property->key());
|
||||
builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
|
||||
obj, feedback_index(slot), language_mode());
|
||||
object, feedback_index(slot), language_mode());
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
PrepareNamedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(),
|
||||
property->key()->AsLiteral()->AsPropertyName(), &super_args);
|
||||
BuildNamedSuperPropertyLoad(&super_args);
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
PrepareKeyedSuperPropertyArguments(
|
||||
property->obj()->AsSuperPropertyReference(), property->key(),
|
||||
&super_args);
|
||||
BuildKeyedSuperPropertyLoad(&super_args);
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
// Convert old value into a number.
|
||||
@ -2504,18 +2737,23 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
break;
|
||||
}
|
||||
case NAMED_PROPERTY: {
|
||||
builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot),
|
||||
builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot),
|
||||
language_mode());
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot),
|
||||
builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot),
|
||||
language_mode());
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
UNIMPLEMENTED();
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
BuildNamedSuperPropertyStore(&super_args);
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
BuildKeyedSuperPropertyStore(&super_args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore old value for postfix expressions.
|
||||
@ -2575,13 +2813,15 @@ void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
|
||||
UNIMPLEMENTED();
|
||||
// Handled by VisitCall().
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitSuperPropertyReference(
|
||||
SuperPropertyReference* expr) {
|
||||
UNIMPLEMENTED();
|
||||
builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
|
||||
@ -2754,14 +2994,17 @@ void BytecodeGenerator::VisitObjectLiteralAccessor(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
|
||||
ObjectLiteralProperty* property,
|
||||
int slot_number) {
|
||||
Expression* expr = property->value();
|
||||
if (!FunctionLiteral::NeedsHomeObject(expr)) return;
|
||||
|
||||
UNIMPLEMENTED();
|
||||
if (FunctionLiteral::NeedsHomeObject(expr)) {
|
||||
Handle<Name> name = isolate()->factory()->home_object_symbol();
|
||||
FeedbackVectorSlot slot = property->GetSlot(slot_number);
|
||||
builder()
|
||||
->LoadAccumulatorWithRegister(home_object)
|
||||
.StoreNamedProperty(value, name, feedback_index(slot), language_mode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2794,9 +3037,6 @@ void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
|
||||
void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
|
||||
if (variable == nullptr) return;
|
||||
|
||||
// TODO(rmcilroy): Remove once we have tests which exercise this code path.
|
||||
UNIMPLEMENTED();
|
||||
|
||||
// Store the closure we were called with in the given variable.
|
||||
builder()->LoadAccumulatorWithRegister(Register::function_closure());
|
||||
VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
|
||||
|
@ -42,6 +42,7 @@ class BytecodeGenerator final : public AstVisitor {
|
||||
class AccumulatorResultScope;
|
||||
class RegisterResultScope;
|
||||
class RegisterAllocationScope;
|
||||
class SuperPropertyArguments;
|
||||
|
||||
void MakeBytecodeBody();
|
||||
|
||||
@ -65,6 +66,20 @@ class BytecodeGenerator final : public AstVisitor {
|
||||
// Helper visitors which perform common operations.
|
||||
Register VisitArguments(ZoneList<Expression*>* arguments);
|
||||
|
||||
// Visit a keyed super property load. The optional
|
||||
// |opt_receiver_out| register will have the receiver stored to it
|
||||
// if it's a valid register. The loaded value is placed in the
|
||||
// accumulator.
|
||||
void VisitKeyedSuperPropertyLoad(Property* property,
|
||||
Register opt_receiver_out);
|
||||
|
||||
// Visit a named super property load. The optional
|
||||
// |opt_receiver_out| register will have the receiver stored to it
|
||||
// if it's a valid register. The loaded value is placed in the
|
||||
// accumulator.
|
||||
void VisitNamedSuperPropertyLoad(Property* property,
|
||||
Register opt_receiver_out);
|
||||
|
||||
void VisitPropertyLoad(Register obj, Property* expr);
|
||||
void VisitPropertyLoadForAccumulator(Register obj, Property* expr);
|
||||
|
||||
@ -79,6 +94,19 @@ class BytecodeGenerator final : public AstVisitor {
|
||||
void VisitVariableAssignment(Variable* variable, Token::Value op,
|
||||
FeedbackVectorSlot slot);
|
||||
|
||||
void PrepareNamedSuperPropertyArguments(
|
||||
SuperPropertyReference* super_property, Handle<Name> name,
|
||||
SuperPropertyArguments* super_property_args);
|
||||
void PrepareKeyedSuperPropertyArguments(
|
||||
SuperPropertyReference* super_property, Expression* key,
|
||||
SuperPropertyArguments* super_property_args);
|
||||
void BuildNamedSuperPropertyLoad(SuperPropertyArguments* super_property_args);
|
||||
void BuildKeyedSuperPropertyLoad(SuperPropertyArguments* super_property_args);
|
||||
void BuildNamedSuperPropertyStore(
|
||||
SuperPropertyArguments* super_property_args);
|
||||
void BuildKeyedSuperPropertyStore(
|
||||
SuperPropertyArguments* super_property_args);
|
||||
|
||||
void BuildThrowIfHole(Handle<String> name);
|
||||
void BuildThrowIfNotHole(Handle<String> name);
|
||||
void BuildThrowReassignConstant(Handle<String> name);
|
||||
@ -88,6 +116,7 @@ class BytecodeGenerator final : public AstVisitor {
|
||||
|
||||
void VisitArgumentsObject(Variable* variable);
|
||||
void VisitRestArgumentsArray(Variable* rest);
|
||||
void VisitCallSuper(Call* call);
|
||||
void VisitClassLiteralContents(ClassLiteral* expr);
|
||||
void VisitClassLiteralForRuntimeDefinition(ClassLiteral* expr);
|
||||
void VisitClassLiteralProperties(ClassLiteral* expr, Register literal,
|
||||
@ -130,6 +159,10 @@ class BytecodeGenerator final : public AstVisitor {
|
||||
bool IsInsideTryCatch() const { return try_catch_nesting_level_ > 0; }
|
||||
bool IsInsideTryFinally() const { return try_finally_nesting_level_ > 0; }
|
||||
|
||||
// Initialize an array of temporary registers with consecutive registers.
|
||||
template <size_t N>
|
||||
void InitializeWithConsecutiveRegisters(Register (®isters)[N]);
|
||||
|
||||
inline void set_builder(BytecodeArrayBuilder* builder) { builder_ = builder; }
|
||||
inline BytecodeArrayBuilder* builder() const { return builder_; }
|
||||
|
||||
|
@ -224,6 +224,14 @@ Register BytecodeRegisterAllocator::NextConsecutiveRegister() {
|
||||
return Register(next_consecutive_register_++);
|
||||
}
|
||||
|
||||
void BytecodeRegisterAllocator::PrepareAndInitializeConsecutiveAllocations(
|
||||
Register* registers, size_t count) {
|
||||
PrepareForConsecutiveAllocations(count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
registers[i] = NextConsecutiveRegister();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -74,11 +74,22 @@ class BytecodeRegisterAllocator final {
|
||||
~BytecodeRegisterAllocator();
|
||||
Register NewRegister();
|
||||
|
||||
// Ensure |count| consecutive allocations are available.
|
||||
void PrepareForConsecutiveAllocations(size_t count);
|
||||
|
||||
// Get the next consecutive allocation after calling
|
||||
// PrepareForConsecutiveAllocations.
|
||||
Register NextConsecutiveRegister();
|
||||
|
||||
// Prepare consecutive register allocations and initialize an array
|
||||
// of registers with the allocations.
|
||||
void PrepareAndInitializeConsecutiveAllocations(Register* registers,
|
||||
size_t count);
|
||||
|
||||
// Returns true if |reg| is allocated in this allocator.
|
||||
bool RegisterIsAllocatedInThisScope(Register reg) const;
|
||||
|
||||
// Returns true if unused consecutive allocations remain.
|
||||
bool HasConsecutiveAllocations() const { return next_consecutive_count_ > 0; }
|
||||
|
||||
private:
|
||||
|
@ -1166,14 +1166,15 @@ void Interpreter::DoCallJSRuntimeWide(InterpreterAssembler* assembler) {
|
||||
|
||||
void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
|
||||
Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
|
||||
Node* new_target = __ GetAccumulator();
|
||||
Node* constructor_reg = __ BytecodeOperandReg(0);
|
||||
Node* constructor = __ LoadRegister(constructor_reg);
|
||||
Node* first_arg_reg = __ BytecodeOperandReg(1);
|
||||
Node* first_arg = __ RegisterLocation(first_arg_reg);
|
||||
Node* args_count = __ BytecodeOperandCount(2);
|
||||
Node* context = __ GetContext();
|
||||
Node* result = __ CallConstruct(constructor, context, constructor, first_arg,
|
||||
args_count);
|
||||
Node* result =
|
||||
__ CallConstruct(constructor, context, new_target, first_arg, args_count);
|
||||
__ SetAccumulator(result);
|
||||
__ Dispatch();
|
||||
}
|
||||
@ -1183,6 +1184,7 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Call operator new with |constructor| and the first argument in
|
||||
// register |first_arg| and |arg_count| arguments in subsequent
|
||||
// registers. The new.target is in the accumulator.
|
||||
//
|
||||
void Interpreter::DoNew(InterpreterAssembler* assembler) {
|
||||
DoCallConstruct(assembler);
|
||||
@ -1193,6 +1195,7 @@ void Interpreter::DoNew(InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Call operator new with |constructor| and the first argument in
|
||||
// register |first_arg| and |arg_count| arguments in subsequent
|
||||
// registers. The new.target is in the accumulator.
|
||||
//
|
||||
void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
|
||||
DoCallConstruct(assembler);
|
||||
|
@ -504,45 +504,6 @@
|
||||
# TODO(rmcilroy,4680): Check failed: toplevel_test_code_event_found.
|
||||
'test-serialize/SerializeToplevelIsolates': [FAIL],
|
||||
|
||||
# TODO(rmcilroy,4682): Requires support for classes.
|
||||
'test-inobject-slack-tracking/SubclassBasicNoBaseClassInstancesNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassBasicNoBaseClassInstances': [FAIL],
|
||||
'test-inobject-slack-tracking/LongSubclassChain2': [FAIL],
|
||||
'test-inobject-slack-tracking/LongSubclassChain1': [FAIL],
|
||||
'test-inobject-slack-tracking/LongSubclassChain3': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassBasicNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/InobjectPropetiesCountOverflowInSubclass': [FAIL],
|
||||
'test-inobject-slack-tracking/SlowModeSubclass': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassObjectBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassObjectBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassFunctionBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassBasic': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassFunctionBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassNumberBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassBooleanBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassErrorBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassErrorBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassStringBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassDateBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassRegExpBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassStringBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassBooleanBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassDateBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassArrayBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassRegExpBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassNumberBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassArrayBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassTypedArrayBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassTypedArrayBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassCollectionBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassCollectionBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassArrayBufferBuiltin': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassArrayBufferBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassPromiseBuiltinNoInlineNew': [FAIL],
|
||||
'test-inobject-slack-tracking/SubclassPromiseBuiltin': [FAIL],
|
||||
'test-api/Regress470113': [FAIL],
|
||||
'test-api/SubclassGetConstructorName': [FAIL],
|
||||
|
||||
# BUG(4333). Function name inferrer does not work for ES6 clases.
|
||||
'test-func-name-inference/UpperCaseClass': [TIMEOUT],
|
||||
'test-func-name-inference/LowerCaseClass': [TIMEOUT],
|
||||
@ -649,6 +610,7 @@
|
||||
['ignition == True and arch == arm64', {
|
||||
# TODO(rmcilroy,4680): Arm64 specific crashes.
|
||||
'test-api/ExternalWrap': [SKIP],
|
||||
'test-api/Regress470113': [SKIP],
|
||||
'test-heap/NoWeakHashTableLeakWithIncrementalMarking': [SKIP],
|
||||
|
||||
# TODO(rmcilroy,4680): Arm64 flakes.
|
||||
|
@ -5048,13 +5048,14 @@ TEST(CallNew) {
|
||||
"f()",
|
||||
2 * kPointerSize,
|
||||
1,
|
||||
15,
|
||||
17,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(0), //
|
||||
B(LdaSmi8), U8(3), //
|
||||
B(Star), R(1), //
|
||||
B(Ldar), R(0), //
|
||||
B(New), R(0), R(1), U8(1), //
|
||||
B(Return), //
|
||||
},
|
||||
@ -5070,7 +5071,7 @@ TEST(CallNew) {
|
||||
"f()",
|
||||
4 * kPointerSize,
|
||||
1,
|
||||
23,
|
||||
25,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
@ -5081,6 +5082,7 @@ TEST(CallNew) {
|
||||
B(Star), R(2), //
|
||||
B(LdaSmi8), U8(5), //
|
||||
B(Star), R(3), //
|
||||
B(Ldar), R(0), //
|
||||
B(New), R(0), R(1), U8(3), //
|
||||
B(Return), //
|
||||
},
|
||||
@ -9232,6 +9234,8 @@ TEST(ClassDeclarations) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(oth): Add tests for super keyword.
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -3865,6 +3865,65 @@ TEST(InterpreterClassLiterals) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InterpreterClassAndSuperClass) {
|
||||
HandleAndZoneScope handles;
|
||||
i::Isolate* isolate = handles.main_isolate();
|
||||
std::pair<const char*, Handle<Object>> examples[] = {
|
||||
{"class A {\n"
|
||||
" constructor(x) { this.x_ = x; }\n"
|
||||
" method() { return this.x_; }\n"
|
||||
"}\n"
|
||||
"class B extends A {\n"
|
||||
" constructor(x, y) { super(x); this.y_ = y; }\n"
|
||||
" method() { return super.method() + 1; }\n"
|
||||
"}\n"
|
||||
"return new B(998, 0).method();\n",
|
||||
handle(Smi::FromInt(999), isolate)},
|
||||
{"class A {\n"
|
||||
" constructor() { this.x_ = 2; this.y_ = 3; }\n"
|
||||
"}\n"
|
||||
"class B extends A {\n"
|
||||
" constructor() { super(); }"
|
||||
" method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
|
||||
"}\n"
|
||||
"return new B().method();\n",
|
||||
handle(Smi::FromInt(7), isolate)},
|
||||
{"var calls = 0;\n"
|
||||
"class B {}\n"
|
||||
"B.prototype.x = 42;\n"
|
||||
"class C extends B {\n"
|
||||
" constructor() {\n"
|
||||
" super();\n"
|
||||
" calls++;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"new C;\n"
|
||||
"return calls;\n",
|
||||
handle(Smi::FromInt(1), isolate)},
|
||||
{"class A {\n"
|
||||
" method() { return 1; }\n"
|
||||
" get x() { return 2; }\n"
|
||||
"}\n"
|
||||
"class B extends A {\n"
|
||||
" method() { return super.x === 2 ? super.method() : -1; }\n"
|
||||
"}\n"
|
||||
"return new B().method();\n",
|
||||
handle(Smi::FromInt(1), isolate)},
|
||||
{"var object = { setY(v) { super.y = v; }};\n"
|
||||
"object.setY(10);\n"
|
||||
"return object.y;\n",
|
||||
handle(Smi::FromInt(10), isolate)},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(examples); ++i) {
|
||||
std::string source(InterpreterTester::SourceForBody(examples[i].first));
|
||||
InterpreterTester tester(handles.main_isolate(), source.c_str());
|
||||
auto callable = tester.GetCallable<>();
|
||||
Handle<i::Object> return_value = callable().ToHandleChecked();
|
||||
CHECK(return_value->SameValue(*examples[i].second));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InterpreterConstDeclaration) {
|
||||
HandleAndZoneScope handles;
|
||||
i::Isolate* isolate = handles.main_isolate();
|
||||
|
@ -800,6 +800,7 @@
|
||||
'es6/iterator-prototype': [FAIL],
|
||||
'es6/generators-mirror': [FAIL],
|
||||
'es6/object-literals-method': [FAIL],
|
||||
'es6/object-literals-super': [FAIL],
|
||||
'es6/generators-relocation': [FAIL],
|
||||
'es6/spread-array': [FAIL],
|
||||
'es6/generators-debug-liveedit': [FAIL],
|
||||
@ -828,46 +829,6 @@
|
||||
'es6/promises': [FAIL],
|
||||
'deserialize-optimize-inner': [FAIL],
|
||||
|
||||
# TODO(oth,4682): Requires VisitThisFunctionVariable support.
|
||||
'es6/classes-maps': [FAIL],
|
||||
'es6/array-concat': [FAIL],
|
||||
'es6/classes-subclass-arrays': [FAIL],
|
||||
'es6/classes-derived-return-type': [FAIL],
|
||||
'es6/classes-experimental': [FAIL],
|
||||
'es6/legacy-subclassing': [FAIL],
|
||||
'es6/new-target': [FAIL],
|
||||
'es6/promise-internal-setter': [FAIL],
|
||||
'es6/regexp-constructor': [FAIL],
|
||||
'es6/rest-params': [FAIL],
|
||||
'es6/spread-call-new-class': [FAIL],
|
||||
'es6/typedarray-of': [FAIL],
|
||||
'harmony/array-species': [FAIL],
|
||||
'harmony/arraybuffer-species': [FAIL],
|
||||
'harmony/promise-species': [FAIL],
|
||||
'es6/debug-break-default-constructor': [FAIL],
|
||||
'harmony/typedarray-species': [FAIL],
|
||||
'regress/regress-544991': [FAIL],
|
||||
'regress/regress-crbug-498022': [FAIL],
|
||||
'regress/regress-crbug-575080': [FAIL],
|
||||
'regress/regress-crbug-580506': [FAIL],
|
||||
'regress/regress-typedarray-length': [FAIL],
|
||||
|
||||
# TODO(oth,4682): Requires VisitSetHomeObject support.
|
||||
'es6/class-computed-property-names-super': [FAIL],
|
||||
'es6/classes-lazy-parsing': [FAIL],
|
||||
'es6/computed-property-names-super': [FAIL],
|
||||
'es6/classes': [FAIL],
|
||||
'es6/object-literals-super': [FAIL],
|
||||
'es6/spread-call-super-property': [FAIL],
|
||||
'es6/super': [FAIL],
|
||||
'es6/regress/regress-4097': [FAIL],
|
||||
'es6/regress/regress-4466': [FAIL],
|
||||
'es6/regress/regress-4522': [FAIL],
|
||||
'es6/regress/regress-cr493566': [FAIL],
|
||||
'harmony/regress/regress-4395': [FAIL],
|
||||
'regress/regress-4525': [FAIL],
|
||||
'regress/regress-4521': [FAIL],
|
||||
|
||||
# TODO(rmcilroy,4680): Check failed in
|
||||
# BytecodeGenerator::VisitFunctionLiteral - !shared_info.is_null().
|
||||
'regress/regress-crbug-429159': [FAIL],
|
||||
@ -888,12 +849,10 @@
|
||||
'es6/tail-call': [FAIL],
|
||||
'es6/tail-call-simple': [FAIL],
|
||||
'es6/mirror-collections': [FAIL],
|
||||
'es6/block-const-assign': [FAIL],
|
||||
'es6/regress/regress-468661': [FAIL],
|
||||
'harmony/string-replace': [FAIL],
|
||||
'harmony/string-match': [FAIL],
|
||||
'harmony/string-split': [FAIL],
|
||||
'harmony/block-const-assign-sloppy': [FAIL],
|
||||
'regress/regress-2618': [FAIL],
|
||||
'regress/regress-4121': [FAIL],
|
||||
'regress/regress-4266': [FAIL],
|
||||
@ -941,9 +900,9 @@
|
||||
# TODO(rmcilroy,4680): Arm64 specific failures.
|
||||
'apply': [SKIP],
|
||||
'array-constructor': [SKIP],
|
||||
'array-store-and-grow': [SKIP],
|
||||
'array-functions-prototype-misc': [SKIP],
|
||||
'array-sort': [SKIP],
|
||||
'array-store-and-grow': [SKIP],
|
||||
'asm/construct-double': [SKIP],
|
||||
'compiler/division-by-constant': [SKIP],
|
||||
'compiler/osr-big': [SKIP],
|
||||
@ -952,17 +911,24 @@
|
||||
'compiler/osr-two': [SKIP],
|
||||
'copy-on-write-assert': [SKIP],
|
||||
'es6/block-conflicts': [SKIP],
|
||||
'es6/block-const-assign': [SKIP],
|
||||
'es6/block-let-declaration': [SKIP],
|
||||
'es6/block-scoping-top-level': [SKIP],
|
||||
'es6/classes-derived-return-type': [SKIP],
|
||||
'es6/regress/regress-2506': [SKIP],
|
||||
'es6/regress/regress-474783': [SKIP],
|
||||
'es6/typedarray-proto': [SKIP],
|
||||
'es6/unscopables': [SKIP],
|
||||
'harmony/arraybuffer-species': [SKIP],
|
||||
'harmony/array-species': [SKIP],
|
||||
'harmony/block-conflicts-sloppy': [SKIP],
|
||||
'harmony/block-const-assign-sloppy': [SKIP],
|
||||
'harmony/block-let-declaration-sloppy': [SKIP],
|
||||
'harmony/block-scoping-top-level-sloppy': [SKIP],
|
||||
'harmony/species': [SKIP],
|
||||
'harmony/typedarray-species': [SKIP],
|
||||
'mirror-object': [SKIP],
|
||||
'mul-exhaustive-part*': [SKIP],
|
||||
'readonly': [SKIP],
|
||||
'regress/regress-165637': [SKIP],
|
||||
'regress/regress-2185': [SKIP],
|
||||
@ -972,20 +938,21 @@
|
||||
'regress/regress-347914': [SKIP],
|
||||
'regress/regress-411210': [SKIP],
|
||||
'regress/regress-4509-Class-constructor-typeerror-realm': [SKIP],
|
||||
'regress/regress-4521': [SKIP],
|
||||
'regress/regress-568765': [SKIP],
|
||||
'regress/regress-85177': [SKIP],
|
||||
'regress/regress-crbug-405517': [SKIP],
|
||||
'regress/regress-crbug-474297': [SKIP],
|
||||
'regress/regress-crbug-498022': [SKIP],
|
||||
'regress/regress-crbug-505007-1': [SKIP],
|
||||
'regress/regress-crbug-505007-2': [SKIP],
|
||||
'regress/regress-crbug-514081': [SKIP],
|
||||
'regress/regress-crbug-513507': [SKIP],
|
||||
'regress/regress-crbug-514081': [SKIP],
|
||||
'regress/regress-deep-proto': [SKIP],
|
||||
'regress/regress-put-prototype-transition': [SKIP],
|
||||
'regress/regress-transcendental': [SKIP],
|
||||
'stack-traces-overflow': [SKIP],
|
||||
'try': [SKIP],
|
||||
'mul-exhaustive-part*': [SKIP],
|
||||
'unicodelctest': [SKIP],
|
||||
'unicodelctest-no-optimization': [SKIP],
|
||||
}], # ignition == True and arch == arm64
|
||||
|
@ -440,16 +440,14 @@
|
||||
'built-ins/Array/prototype/reduceRight/*': [SKIP],
|
||||
'built-ins/GeneratorFunction/*': [SKIP],
|
||||
'built-ins/GeneratorPrototype/*': [SKIP],
|
||||
'built-ins/Promise/prototype/then/capability-executor-called-twice': [SKIP],
|
||||
'built-ins/Promise/prototype/then/capability-executor-not-callable': [SKIP],
|
||||
'built-ins/Promise/prototype/then/deferred-is-resolved-value': [SKIP],
|
||||
'built-ins/Reflect/enumerate/*': [SKIP],
|
||||
'language/computed-property-names/class/*': [SKIP],
|
||||
'language/computed-property-names/to-name-side-effects/*': [SKIP],
|
||||
'language/directive-prologue/*': [SKIP],
|
||||
'language/expressions/arrow-function/*': [SKIP],
|
||||
'language/expressions/assignment/destructuring/*': [SKIP],
|
||||
'language/expressions/class/*': [SKIP],
|
||||
'language/expressions/class/subclass/builtin-objects/GeneratorFunction/*': [SKIP],
|
||||
'language/expressions/generators/*': [SKIP],
|
||||
'language/expressions/instanceof/primitive-prototype-with-object': [SKIP],
|
||||
'language/expressions/instanceof/prototype-getter-with-object-throws': [SKIP],
|
||||
@ -457,7 +455,18 @@
|
||||
'language/expressions/object/method-definition/yield*': [SKIP],
|
||||
'language/expressions/object/method-definition/generator*': [SKIP],
|
||||
'language/expressions/yield/*': [SKIP],
|
||||
'language/statements/class/*': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-no-yield': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-return': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-expression-with-rhs': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-generator-method-binding-identifier': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-literal-property-name': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-property-name': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-statement': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-expression-without-rhs': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-as-yield-operand': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-newline': [SKIP],
|
||||
'language/statements/class/definition/methods-gen-yield-star-before-newline': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/GeneratorFunction/*': [SKIP],
|
||||
'language/statements/generators/*': [SKIP],
|
||||
|
||||
'built-ins/Array/prototype/concat/Array.prototype.concat_non-array': [SKIP],
|
||||
@ -472,12 +481,8 @@
|
||||
'built-ins/Object/prototype/valueOf/S15.2.4.4_A12': [SKIP],
|
||||
'built-ins/Object/prototype/valueOf/S15.2.4.4_A14': [SKIP],
|
||||
'built-ins/Object/prototype/valueOf/S15.2.4.4_A15': [SKIP],
|
||||
'built-ins/Promise/all/ctx-ctor': [SKIP],
|
||||
'built-ins/Promise/all/S25.4.4.1_A4.1_T1': [SKIP],
|
||||
'built-ins/Promise/prototype/then/on-rejected-throw': [SKIP],
|
||||
'built-ins/Promise/race/ctx-ctor': [SKIP],
|
||||
'built-ins/Promise/reject/ctx-ctor': [SKIP],
|
||||
'built-ins/Promise/resolve/ctx-ctor': [SKIP],
|
||||
'built-ins/Promise/reject/S25.4.4.4_A3.1_T1': [SKIP],
|
||||
'built-ins/String/prototype/codePointAt/this-is-undefined-throws': [SKIP],
|
||||
'built-ins/String/prototype/concat/S15.5.4.6_A2': [SKIP],
|
||||
@ -485,20 +490,14 @@
|
||||
'built-ins/String/prototype/includes/this-is-undefined-throws': [SKIP],
|
||||
'built-ins/String/prototype/repeat/this-is-undefined-throws': [SKIP],
|
||||
'built-ins/String/prototype/startsWith/this-is-undefined-throws': [SKIP],
|
||||
'built-ins/Promise/prototype/then/ctor-custom': [SKIP],
|
||||
'built-ins/String/prototype/trim/15.5.4.20-1-1': [SKIP],
|
||||
'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-1': [SKIP],
|
||||
'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-2': [SKIP],
|
||||
'language/block-scope/leave/verify-context-in-labelled-block': [SKIP],
|
||||
'language/block-scope/leave/x-after-break-to-label': [SKIP],
|
||||
'language/computed-property-names/object/accessor/getter-super': [SKIP],
|
||||
'language/computed-property-names/object/accessor/setter-super': [SKIP],
|
||||
'language/computed-property-names/object/method/super': [SKIP],
|
||||
'language/default-parameters/class-definitions': [SKIP],
|
||||
'language/default-parameters/generators': [SKIP],
|
||||
'language/expressions/object/method-definition/name-prop-name-yield-expr': [SKIP],
|
||||
'language/expressions/object/method-definition/name-super-prop-param': [SKIP],
|
||||
'language/expressions/object/method-definition/name-super-prop-body': [SKIP],
|
||||
'language/expressions/tagged-template/call-expression-context-no-strict': [SKIP],
|
||||
'language/expressions/tagged-template/call-expression-context-strict': [SKIP],
|
||||
'language/expressions/template-literal/evaluation-order': [SKIP],
|
||||
@ -538,22 +537,80 @@
|
||||
'language/statements/for-of/yield-star-from-finally': [SKIP],
|
||||
'language/statements/for-of/yield-star-from-try': [SKIP],
|
||||
'language/object-literal/concise-generator': [SKIP],
|
||||
'language/object-literal/getter': [SKIP],
|
||||
'language/object-literal/method': [SKIP],
|
||||
'language/object-literal/setter': [SKIP],
|
||||
'language/rest-parameters/with-new-target': [SKIP],
|
||||
'language/statements/do-while/S12.6.1_A4_T5': [SKIP],
|
||||
'language/statements/while/S12.6.2_A4_T5': [SKIP],
|
||||
|
||||
}], # ignition == True
|
||||
|
||||
['ignition == True and (arch == arm or arch == arm64)', {
|
||||
'built-ins/Promise/all/ctx-ctor': [SKIP],
|
||||
'built-ins/Promise/race/ctx-ctor': [SKIP],
|
||||
'built-ins/decodeURI/S15.1.3.1_A1.12_T3': [SKIP],
|
||||
'built-ins/decodeURIComponent/S15.1.3.2_A1.10_T1': [SKIP],
|
||||
'built-ins/decodeURIComponent/S15.1.3.2_A1.11_T2': [SKIP],
|
||||
'built-ins/decodeURIComponent/S15.1.3.2_A1.12_T2': [SKIP],
|
||||
'built-ins/decodeURIComponent/S15.1.3.2_A1.12_T3': [SKIP],
|
||||
'intl402/9.2.2': [SKIP],
|
||||
'language/statements/class/arguments/default-constructor': [SKIP],
|
||||
'language/statements/class/definition/constructor-strict-by-default': [SKIP],
|
||||
'language/statements/class/definition/fn-name-accessor-get': [SKIP],
|
||||
'language/statements/class/definition/fn-name-accessor-set': [SKIP],
|
||||
'language/statements/class/definition/fn-name-gen-method': [SKIP],
|
||||
'language/statements/class/definition/fn-name-method': [SKIP],
|
||||
'language/statements/class/definition/methods-restricted-properties': [SKIP],
|
||||
'language/statements/class/definition/prototype-getter': [SKIP],
|
||||
'language/statements/class/definition/prototype-wiring': [SKIP],
|
||||
'language/statements/class/definition/this-access-restriction': [SKIP],
|
||||
'language/statements/class/definition/this-access-restriction-2': [SKIP],
|
||||
'language/statements/class/definition/this-check-ordering': [SKIP],
|
||||
'language/statements/class/name': [SKIP],
|
||||
'language/statements/class/restricted-properties': [SKIP],
|
||||
'language/statements/class/subclass/binding': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Array/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/ArrayBuffer/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Boolean/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/DataView/regular-subclassing': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/DataView/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Date/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Error/regular-subclassing': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Error/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Function/instance-length': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Function/instance-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Function/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Map/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/EvalError-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/EvalError-super': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/RangeError-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/RangeError-super': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-super': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-super': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/TypeError-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/TypeError-super': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/URIError-name': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/NativeError/URIError-super': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Number/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Object/constructor-return-undefined-throws': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Object/constructor-returns-non-object': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Promise/regular-subclassing': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Promise/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/RegExp/lastIndex': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/RegExp/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Set/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/String/length': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/String/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/Symbol/new-symbol-with-super-throws': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/WeakMap/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/builtin-objects/WeakSet/super-must-be-called': [SKIP],
|
||||
'language/statements/class/subclass/class-definition-null-proto-missing-return-override': [SKIP],
|
||||
'language/statements/class/subclass/default-constructor': [SKIP],
|
||||
'language/statements/class/subclass/default-constructor-2': [SKIP],
|
||||
'language/statements/class/subclass/derived-class-return-override-with-boolean': [SKIP],
|
||||
'language/statements/class/subclass/derived-class-return-override-with-null': [SKIP],
|
||||
'language/statements/class/subclass/derived-class-return-override-with-number': [SKIP],
|
||||
'language/statements/class/subclass/derived-class-return-override-with-string': [SKIP],
|
||||
'language/statements/class/subclass/derived-class-return-override-with-symbol': [SKIP],
|
||||
'language/statements/const/fn-name-arrow': [SKIP],
|
||||
'language/statements/const/fn-name-class': [SKIP],
|
||||
'language/statements/const/fn-name-cover': [SKIP],
|
||||
@ -564,6 +621,7 @@
|
||||
'language/statements/let/fn-name-cover': [SKIP],
|
||||
'language/statements/let/fn-name-fn': [SKIP],
|
||||
'language/statements/let/fn-name-gen': [SKIP],
|
||||
'test-api/Regress470113': [SKIP],
|
||||
}], # ignition == True and (arch == arm or arch == arm64)
|
||||
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user