Commit 84741e76 authored by arv@chromium.org's avatar arv@chromium.org

ES6: Add support for super in object literals

This only available under --harmony-classes

BUG=v8:3571
LOG=Y
R=dslomov@chromium.org

Review URL: https://codereview.chromium.org/718473002

Cr-Commit-Position: refs/heads/master@{#25271}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25271 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1386257c
...@@ -1383,6 +1383,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { ...@@ -1383,6 +1383,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
} }
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
__ mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ ldr(StoreDescriptor::ValueRegister(),
MemOperand(sp, offset * kPointerSize));
CallStoreIC();
}
}
void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
TypeofState typeof_state, TypeofState typeof_state,
Label* slow) { Label* slow) {
...@@ -1739,6 +1752,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1739,6 +1752,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(key->LiteralFeedbackId()); CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS); PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
__ Move(StoreDescriptor::ReceiverRegister(), r0);
__ mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ ldr(StoreDescriptor::ValueRegister(), MemOperand(sp));
CallStoreIC();
}
} else { } else {
VisitForEffect(value); VisitForEffect(value);
} }
...@@ -1750,6 +1771,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1750,6 +1771,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
if (property->emit_store()) { if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
__ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes __ mov(r0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes
__ push(r0); __ push(r0);
__ CallRuntime(Runtime::kSetProperty, 4); __ CallRuntime(Runtime::kSetProperty, 4);
...@@ -1787,7 +1809,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1787,7 +1809,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(r0); __ push(r0);
VisitForStackValue(it->first); VisitForStackValue(it->first);
EmitAccessor(it->second->getter); EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitAccessor(it->second->setter); EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
__ mov(r0, Operand(Smi::FromInt(NONE))); __ mov(r0, Operand(Smi::FromInt(NONE)));
__ push(r0); __ push(r0);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
...@@ -2534,6 +2558,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2534,6 +2558,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
__ push(scratch); __ push(scratch);
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
......
...@@ -1372,6 +1372,18 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { ...@@ -1372,6 +1372,18 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
} }
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
__ Mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
CallStoreIC();
}
}
void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
TypeofState typeof_state, TypeofState typeof_state,
Label* slow) { Label* slow) {
...@@ -1721,6 +1733,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1721,6 +1733,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Peek(StoreDescriptor::ReceiverRegister(), 0); __ Peek(StoreDescriptor::ReceiverRegister(), 0);
CallStoreIC(key->LiteralFeedbackId()); CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS); PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
__ Mov(StoreDescriptor::ReceiverRegister(), x0);
__ Mov(StoreDescriptor::NameRegister(),
Operand(isolate()->factory()->home_object_symbol()));
__ Peek(StoreDescriptor::ValueRegister(), 0);
CallStoreIC();
}
} else { } else {
VisitForEffect(value); VisitForEffect(value);
} }
...@@ -1732,6 +1752,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1732,6 +1752,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Push(x0); __ Push(x0);
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
__ Mov(x0, Smi::FromInt(SLOPPY)); // Strict mode __ Mov(x0, Smi::FromInt(SLOPPY)); // Strict mode
__ Push(x0); __ Push(x0);
__ CallRuntime(Runtime::kSetProperty, 4); __ CallRuntime(Runtime::kSetProperty, 4);
...@@ -1769,7 +1790,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1769,7 +1790,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Push(x10); __ Push(x10);
VisitForStackValue(it->first); VisitForStackValue(it->first);
EmitAccessor(it->second->getter); EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitAccessor(it->second->setter); EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
__ Mov(x10, Smi::FromInt(NONE)); __ Mov(x10, Smi::FromInt(NONE));
__ Push(x10); __ Push(x10);
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
...@@ -2203,6 +2226,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2203,6 +2226,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
__ Push(scratch); __ Push(scratch);
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
......
...@@ -151,6 +151,12 @@ StrictMode FunctionLiteral::strict_mode() const { ...@@ -151,6 +151,12 @@ StrictMode FunctionLiteral::strict_mode() const {
} }
bool FunctionLiteral::needs_super_binding() const {
DCHECK_NOT_NULL(scope());
return scope()->uses_super() || scope()->inner_uses_super();
}
void FunctionLiteral::InitializeSharedInfo( void FunctionLiteral::InitializeSharedInfo(
Handle<Code> unoptimized_code) { Handle<Code> unoptimized_code) {
for (RelocIterator it(*unoptimized_code); !it.done(); it.next()) { for (RelocIterator it(*unoptimized_code); !it.done(); it.next()) {
......
...@@ -2497,6 +2497,12 @@ class FunctionLiteral FINAL : public Expression { ...@@ -2497,6 +2497,12 @@ class FunctionLiteral FINAL : public Expression {
bool is_expression() const { return IsExpression::decode(bitfield_); } bool is_expression() const { return IsExpression::decode(bitfield_); }
bool is_anonymous() const { return IsAnonymous::decode(bitfield_); } bool is_anonymous() const { return IsAnonymous::decode(bitfield_); }
StrictMode strict_mode() const; StrictMode strict_mode() const;
bool needs_super_binding() const;
static bool NeedsHomeObject(Expression* literal) {
return literal != NULL && literal->IsFunctionLiteral() &&
literal->AsFunctionLiteral()->needs_super_binding();
}
int materialized_literal_count() { return materialized_literal_count_; } int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; } int expected_property_count() { return expected_property_count_; }
......
...@@ -614,6 +614,15 @@ class FullCodeGenerator: public AstVisitor { ...@@ -614,6 +614,15 @@ class FullCodeGenerator: public AstVisitor {
void EmitLoadHomeObject(SuperReference* expr); void EmitLoadHomeObject(SuperReference* expr);
static bool NeedsHomeObject(Expression* expr) {
return FunctionLiteral::NeedsHomeObject(expr);
}
// Adds the [[HomeObject]] to |initializer| if it is a FunctionLiteral.
// The value of the initializer is expected to be at the top of the stack.
// |offset| is the offset in the stack where the home object can be found.
void EmitSetHomeObjectIfNeeded(Expression* initializer, int offset);
void EmitLoadSuperConstructor(SuperReference* expr); void EmitLoadSuperConstructor(SuperReference* expr);
void CallIC(Handle<Code> code, void CallIC(Handle<Code> code,
......
...@@ -5653,6 +5653,17 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -5653,6 +5653,17 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
if (property->emit_store()) { if (property->emit_store()) {
CHECK_ALIVE(VisitForValue(value)); CHECK_ALIVE(VisitForValue(value));
HValue* value = Pop(); HValue* value = Pop();
// Add [[HomeObject]] to function literals.
if (FunctionLiteral::NeedsHomeObject(property->value())) {
Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
HInstruction* store_home = BuildKeyedGeneric(
STORE, NULL, value, Add<HConstant>(sym), literal);
AddInstruction(store_home);
DCHECK(store_home->HasObservableSideEffects());
Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
}
Handle<Map> map = property->GetReceiverType(); Handle<Map> map = property->GetReceiverType();
Handle<String> name = property->key()->AsPropertyName(); Handle<String> name = property->key()->AsPropertyName();
HInstruction* store; HInstruction* store;
...@@ -5674,9 +5685,8 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -5674,9 +5685,8 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
} }
} }
AddInstruction(store); AddInstruction(store);
if (store->HasObservableSideEffects()) { DCHECK(store->HasObservableSideEffects());
Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
}
} else { } else {
CHECK_ALIVE(VisitForEffect(value)); CHECK_ALIVE(VisitForEffect(value));
} }
......
...@@ -1306,6 +1306,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { ...@@ -1306,6 +1306,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
} }
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
__ mov(StoreDescriptor::NameRegister(),
Immediate(isolate()->factory()->home_object_symbol()));
__ mov(StoreDescriptor::ValueRegister(),
Operand(esp, offset * kPointerSize));
CallStoreIC();
}
}
void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
TypeofState typeof_state, TypeofState typeof_state,
Label* slow) { Label* slow) {
...@@ -1670,6 +1683,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1670,6 +1683,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
CallStoreIC(key->LiteralFeedbackId()); CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS); PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
__ mov(StoreDescriptor::ReceiverRegister(), eax);
__ mov(StoreDescriptor::NameRegister(),
Immediate(isolate()->factory()->home_object_symbol()));
__ mov(StoreDescriptor::ValueRegister(), Operand(esp, 0));
CallStoreIC();
}
} else { } else {
VisitForEffect(value); VisitForEffect(value);
} }
...@@ -1679,6 +1700,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1679,6 +1700,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
if (property->emit_store()) { if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
__ push(Immediate(Smi::FromInt(SLOPPY))); // Strict mode __ push(Immediate(Smi::FromInt(SLOPPY))); // Strict mode
__ CallRuntime(Runtime::kSetProperty, 4); __ CallRuntime(Runtime::kSetProperty, 4);
} else { } else {
...@@ -1711,7 +1733,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1711,7 +1733,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(Operand(esp, 0)); // Duplicate receiver. __ push(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(it->first); VisitForStackValue(it->first);
EmitAccessor(it->second->getter); EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitAccessor(it->second->setter); EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
__ push(Immediate(Smi::FromInt(NONE))); __ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
} }
...@@ -2448,6 +2472,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2448,6 +2472,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
} }
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
......
...@@ -965,6 +965,7 @@ class PreParserScope { ...@@ -965,6 +965,7 @@ class PreParserScope {
bool IsDeclared(const PreParserIdentifier& identifier) const { return false; } bool IsDeclared(const PreParserIdentifier& identifier) const { return false; }
void DeclareParameter(const PreParserIdentifier& identifier, VariableMode) {} void DeclareParameter(const PreParserIdentifier& identifier, VariableMode) {}
void RecordArgumentsUsage() {} void RecordArgumentsUsage() {}
void RecordSuperUsage() {}
void RecordThisUsage() {} void RecordThisUsage() {}
// Allow scope->Foo() to work. // Allow scope->Foo() to work.
...@@ -2508,6 +2509,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) { ...@@ -2508,6 +2509,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
int new_pos = position(); int new_pos = position();
ExpressionT result = this->EmptyExpression(); ExpressionT result = this->EmptyExpression();
if (Check(Token::SUPER)) { if (Check(Token::SUPER)) {
scope_->RecordSuperUsage();
result = this->SuperReference(scope_, factory()); result = this->SuperReference(scope_, factory());
} else { } else {
result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
...@@ -2567,6 +2569,7 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) { ...@@ -2567,6 +2569,7 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
} else if (peek() == Token::SUPER) { } else if (peek() == Token::SUPER) {
int beg_pos = position(); int beg_pos = position();
Consume(Token::SUPER); Consume(Token::SUPER);
scope_->RecordSuperUsage();
Token::Value next = peek(); Token::Value next = peek();
if (next == Token::PERIOD || next == Token::LBRACK || if (next == Token::PERIOD || next == Token::LBRACK ||
next == Token::LPAREN) { next == Token::LPAREN) {
......
...@@ -113,6 +113,8 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { ...@@ -113,6 +113,8 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
isolate, JSObject::SetOwnPropertyIgnoreAttributes( isolate, JSObject::SetOwnPropertyIgnoreAttributes(
constructor, isolate->factory()->prototype_string(), constructor, isolate->factory()->prototype_string(),
prototype, attribs)); prototype, attribs));
// TODO(arv): Only do this conditionally.
Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol()); Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
RETURN_FAILURE_ON_EXCEPTION( RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::SetOwnPropertyIgnoreAttributes( isolate, JSObject::SetOwnPropertyIgnoreAttributes(
...@@ -153,11 +155,6 @@ RUNTIME_FUNCTION(Runtime_DefineClassMethod) { ...@@ -153,11 +155,6 @@ RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2); CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::SetOwnPropertyIgnoreAttributes(
function, isolate->factory()->home_object_symbol(), object,
DONT_ENUM));
uint32_t index; uint32_t index;
if (key->ToArrayIndex(&index)) { if (key->ToArrayIndex(&index)) {
RETURN_FAILURE_ON_EXCEPTION( RETURN_FAILURE_ON_EXCEPTION(
...@@ -189,11 +186,6 @@ RUNTIME_FUNCTION(Runtime_DefineClassGetter) { ...@@ -189,11 +186,6 @@ RUNTIME_FUNCTION(Runtime_DefineClassGetter) {
Handle<Name> name; Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key)); Runtime::ToName(isolate, key));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::SetOwnPropertyIgnoreAttributes(
getter, isolate->factory()->home_object_symbol(), object, DONT_ENUM));
RETURN_FAILURE_ON_EXCEPTION( RETURN_FAILURE_ON_EXCEPTION(
isolate, isolate,
JSObject::DefineAccessor(object, name, getter, JSObject::DefineAccessor(object, name, getter,
...@@ -212,10 +204,6 @@ RUNTIME_FUNCTION(Runtime_DefineClassSetter) { ...@@ -212,10 +204,6 @@ RUNTIME_FUNCTION(Runtime_DefineClassSetter) {
Handle<Name> name; Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key)); Runtime::ToName(isolate, key));
RETURN_FAILURE_ON_EXCEPTION(
isolate,
JSObject::SetOwnPropertyIgnoreAttributes(
setter, isolate->factory()->home_object_symbol(), object, DONT_ENUM));
RETURN_FAILURE_ON_EXCEPTION( RETURN_FAILURE_ON_EXCEPTION(
isolate, isolate,
JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
......
...@@ -160,16 +160,18 @@ void Scope::SetDefaults(ScopeType scope_type, ...@@ -160,16 +160,18 @@ void Scope::SetDefaults(ScopeType scope_type,
scope_inside_with_ = false; scope_inside_with_ = false;
scope_contains_with_ = false; scope_contains_with_ = false;
scope_calls_eval_ = false; scope_calls_eval_ = false;
scope_uses_this_ = false;
scope_uses_arguments_ = false; scope_uses_arguments_ = false;
scope_uses_super_ = false;
scope_uses_this_ = false;
asm_module_ = false; asm_module_ = false;
asm_function_ = outer_scope != NULL && outer_scope->asm_module_; asm_function_ = outer_scope != NULL && outer_scope->asm_module_;
// Inherit the strict mode from the parent scope. // Inherit the strict mode from the parent scope.
strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
outer_scope_calls_sloppy_eval_ = false; outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false; inner_scope_calls_eval_ = false;
inner_scope_uses_this_ = false;
inner_scope_uses_arguments_ = false; inner_scope_uses_arguments_ = false;
inner_scope_uses_this_ = false;
inner_scope_uses_super_ = false;
force_eager_compilation_ = false; force_eager_compilation_ = false;
force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
? outer_scope->has_forced_context_allocation() : false; ? outer_scope->has_forced_context_allocation() : false;
...@@ -889,12 +891,14 @@ void Scope::Print(int n) { ...@@ -889,12 +891,14 @@ void Scope::Print(int n) {
if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
if (scope_uses_this_) Indent(n1, "// scope uses 'this'\n");
if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n");
if (inner_scope_uses_this_) Indent(n1, "// inner scope uses 'this'\n"); if (scope_uses_super_) Indent(n1, "// scope uses 'super'\n");
if (scope_uses_this_) Indent(n1, "// scope uses 'this'\n");
if (inner_scope_uses_arguments_) { if (inner_scope_uses_arguments_) {
Indent(n1, "// inner scope uses 'arguments'\n"); Indent(n1, "// inner scope uses 'arguments'\n");
} }
if (inner_scope_uses_super_) Indent(n1, "// inner scope uses 'super'\n");
if (inner_scope_uses_this_) Indent(n1, "// inner scope uses 'this'\n");
if (outer_scope_calls_sloppy_eval_) { if (outer_scope_calls_sloppy_eval_) {
Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
} }
...@@ -1177,15 +1181,18 @@ void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { ...@@ -1177,15 +1181,18 @@ void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
inner_scope_calls_eval_ = true; inner_scope_calls_eval_ = true;
} }
// If the inner scope is an arrow function, propagate the flags tracking // If the inner scope is an arrow function, propagate the flags tracking
// usage of this/arguments, but do not propagate them out from normal // usage of arguments/super/this, but do not propagate them out from normal
// functions. // functions.
if (!inner->is_function_scope() || inner->is_arrow_scope()) { if (!inner->is_function_scope() || inner->is_arrow_scope()) {
if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) {
inner_scope_uses_this_ = true;
}
if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) { if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) {
inner_scope_uses_arguments_ = true; inner_scope_uses_arguments_ = true;
} }
if (inner->scope_uses_super_ || inner->inner_scope_uses_super_) {
inner_scope_uses_super_ = true;
}
if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) {
inner_scope_uses_this_ = true;
}
} }
if (inner->force_eager_compilation_) { if (inner->force_eager_compilation_) {
force_eager_compilation_ = true; force_eager_compilation_ = true;
......
...@@ -211,12 +211,15 @@ class Scope: public ZoneObject { ...@@ -211,12 +211,15 @@ class Scope: public ZoneObject {
// Inform the scope that the corresponding code contains an eval call. // Inform the scope that the corresponding code contains an eval call.
void RecordEvalCall() { if (!is_global_scope()) scope_calls_eval_ = true; } void RecordEvalCall() { if (!is_global_scope()) scope_calls_eval_ = true; }
// Inform the scope that the corresponding code uses "this".
void RecordThisUsage() { scope_uses_this_ = true; }
// Inform the scope that the corresponding code uses "arguments". // Inform the scope that the corresponding code uses "arguments".
void RecordArgumentsUsage() { scope_uses_arguments_ = true; } void RecordArgumentsUsage() { scope_uses_arguments_ = true; }
// Inform the scope that the corresponding code uses "super".
void RecordSuperUsage() { scope_uses_super_ = true; }
// Inform the scope that the corresponding code uses "this".
void RecordThisUsage() { scope_uses_this_ = true; }
// Set the strict mode flag (unless disabled by a global flag). // Set the strict mode flag (unless disabled by a global flag).
void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; } void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
...@@ -301,14 +304,18 @@ class Scope: public ZoneObject { ...@@ -301,14 +304,18 @@ class Scope: public ZoneObject {
// Does this scope contain a with statement. // Does this scope contain a with statement.
bool contains_with() const { return scope_contains_with_; } bool contains_with() const { return scope_contains_with_; }
// Does this scope access "this".
bool uses_this() const { return scope_uses_this_; }
// Does any inner scope access "this".
bool inner_uses_this() const { return inner_scope_uses_this_; }
// Does this scope access "arguments". // Does this scope access "arguments".
bool uses_arguments() const { return scope_uses_arguments_; } bool uses_arguments() const { return scope_uses_arguments_; }
// Does any inner scope access "arguments". // Does any inner scope access "arguments".
bool inner_uses_arguments() const { return inner_scope_uses_arguments_; } bool inner_uses_arguments() const { return inner_scope_uses_arguments_; }
// Does this scope access "super".
bool uses_super() const { return scope_uses_super_; }
// Does any inner scope access "super".
bool inner_uses_super() const { return inner_scope_uses_super_; }
// Does this scope access "this".
bool uses_this() const { return scope_uses_this_; }
// Does any inner scope access "this".
bool inner_uses_this() const { return inner_scope_uses_this_; }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Accessors. // Accessors.
...@@ -486,10 +493,12 @@ class Scope: public ZoneObject { ...@@ -486,10 +493,12 @@ class Scope: public ZoneObject {
// This scope or a nested catch scope or with scope contain an 'eval' call. At // This scope or a nested catch scope or with scope contain an 'eval' call. At
// the 'eval' call site this scope is the declaration scope. // the 'eval' call site this scope is the declaration scope.
bool scope_calls_eval_; bool scope_calls_eval_;
// This scope uses "this".
bool scope_uses_this_;
// This scope uses "arguments". // This scope uses "arguments".
bool scope_uses_arguments_; bool scope_uses_arguments_;
// This scope uses "super".
bool scope_uses_super_;
// This scope uses "this".
bool scope_uses_this_;
// This scope contains an "use asm" annotation. // This scope contains an "use asm" annotation.
bool asm_module_; bool asm_module_;
// This scope's outer context is an asm module. // This scope's outer context is an asm module.
...@@ -503,8 +512,9 @@ class Scope: public ZoneObject { ...@@ -503,8 +512,9 @@ class Scope: public ZoneObject {
// Computed via PropagateScopeInfo. // Computed via PropagateScopeInfo.
bool outer_scope_calls_sloppy_eval_; bool outer_scope_calls_sloppy_eval_;
bool inner_scope_calls_eval_; bool inner_scope_calls_eval_;
bool inner_scope_uses_this_;
bool inner_scope_uses_arguments_; bool inner_scope_uses_arguments_;
bool inner_scope_uses_super_;
bool inner_scope_uses_this_;
bool force_eager_compilation_; bool force_eager_compilation_;
bool force_context_allocation_; bool force_context_allocation_;
......
...@@ -1341,6 +1341,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { ...@@ -1341,6 +1341,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
} }
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
int offset) {
if (NeedsHomeObject(initializer)) {
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
__ Move(StoreDescriptor::NameRegister(),
isolate()->factory()->home_object_symbol());
__ movp(StoreDescriptor::ValueRegister(),
Operand(rsp, offset * kPointerSize));
CallStoreIC();
}
}
void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
TypeofState typeof_state, TypeofState typeof_state,
Label* slow) { Label* slow) {
...@@ -1704,6 +1717,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1704,6 +1717,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
CallStoreIC(key->LiteralFeedbackId()); CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS); PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
__ movp(StoreDescriptor::ReceiverRegister(), rax);
__ Move(StoreDescriptor::NameRegister(),
isolate()->factory()->home_object_symbol());
__ movp(StoreDescriptor::ValueRegister(), Operand(rsp, 0));
CallStoreIC();
}
} else { } else {
VisitForEffect(value); VisitForEffect(value);
} }
...@@ -1713,6 +1734,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1713,6 +1734,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
if (property->emit_store()) { if (property->emit_store()) {
EmitSetHomeObjectIfNeeded(value, 2);
__ Push(Smi::FromInt(SLOPPY)); // Strict mode __ Push(Smi::FromInt(SLOPPY)); // Strict mode
__ CallRuntime(Runtime::kSetProperty, 4); __ CallRuntime(Runtime::kSetProperty, 4);
} else { } else {
...@@ -1745,7 +1767,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1745,7 +1767,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Push(Operand(rsp, 0)); // Duplicate receiver. __ Push(Operand(rsp, 0)); // Duplicate receiver.
VisitForStackValue(it->first); VisitForStackValue(it->first);
EmitAccessor(it->second->getter); EmitAccessor(it->second->getter);
EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitAccessor(it->second->setter); EmitAccessor(it->second->setter);
EmitSetHomeObjectIfNeeded(it->second->setter, 3);
__ Push(Smi::FromInt(NONE)); __ Push(Smi::FromInt(NONE));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
} }
...@@ -2447,6 +2471,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2447,6 +2471,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
} }
VisitForStackValue(key); VisitForStackValue(key);
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2);
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
......
...@@ -919,7 +919,7 @@ static int Utf8LengthHelper(const char* s) { ...@@ -919,7 +919,7 @@ static int Utf8LengthHelper(const char* s) {
} }
TEST(ScopeUsesThisAndArguments) { TEST(ScopeUsesArgumentsSuperThis) {
static const struct { static const struct {
const char* prefix; const char* prefix;
const char* suffix; const char* suffix;
...@@ -928,62 +928,66 @@ TEST(ScopeUsesThisAndArguments) { ...@@ -928,62 +928,66 @@ TEST(ScopeUsesThisAndArguments) {
{ "var f = () => {", "}" }, { "var f = () => {", "}" },
}; };
enum Expected {
NONE = 0,
ARGUMENTS = 1,
SUPER = 2,
THIS = 4,
INNER_ARGUMENTS = 8,
INNER_SUPER = 16,
INNER_THIS = 32
};
static const struct { static const struct {
const char* body; const char* body;
bool uses_this; int expected;
bool uses_arguments;
bool inner_uses_this;
bool inner_uses_arguments;
} source_data[] = { } source_data[] = {
{ "", {"", NONE},
false, false, false, false }, {"return this", THIS},
{ "return this", {"return arguments", ARGUMENTS},
true, false, false, false }, {"return super()", SUPER},
{ "return arguments", {"return super.x", SUPER},
false, true, false, false }, {"return arguments[0]", ARGUMENTS},
{ "return arguments[0]", {"return this + arguments[0]", ARGUMENTS | THIS},
false, true, false, false }, {"return this + arguments[0] + super.x", ARGUMENTS | SUPER | THIS},
{ "return this + arguments[0]", {"return x => this + x", INNER_THIS},
true, true, false, false }, {"return x => super() + x", INNER_SUPER},
{ "return x => this + x", {"this.foo = 42;", THIS},
false, false, true, false }, {"this.foo();", THIS},
{ "this.foo = 42;", {"if (foo()) { this.f() }", THIS},
true, false, false, false }, {"if (foo()) { super.f() }", SUPER},
{ "this.foo();", {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
true, false, false, false }, {"while (true) { this.f() }", THIS},
{ "if (foo()) { this.f() }", {"while (true) { super.f() }", SUPER},
true, false, false, false }, {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
{ "if (arguments.length) { this.f() }", // Multiple nesting levels must work as well.
true, true, false, false }, {"while (true) { while (true) { while (true) return this } }", THIS},
{ "while (true) { this.f() }", {"while (true) { while (true) { while (true) return super() } }",
true, false, false, false }, SUPER},
{ "if (true) { while (true) this.foo(arguments) }", {"if (1) { return () => { while (true) new this() } }", INNER_THIS},
true, true, false, false }, {"if (1) { return () => { while (true) new super() } }", INNER_SUPER},
// Multiple nesting levels must work as well. // Note that propagation of the inner_uses_this() value does not
{ "while (true) { while (true) { while (true) return this } }", // cross boundaries of normal functions onto parent scopes.
true, false, false, false }, {"return function (x) { return this + x }", NONE},
{ "if (1) { return () => { while (true) new this() } }", {"return function (x) { return super() + x }", NONE},
false, false, true, false }, {"var x = function () { this.foo = 42 };", NONE},
// Note that propagation of the inner_uses_this() value does not {"var x = function () { super.foo = 42 };", NONE},
// cross boundaries of normal functions onto parent scopes. {"if (1) { return function () { while (true) new this() } }", NONE},
{ "return function (x) { return this + x }", {"if (1) { return function () { while (true) new super() } }", NONE},
false, false, false, false }, {"return function (x) { return () => this }", NONE},
{ "var x = function () { this.foo = 42 };", {"return function (x) { return () => super() }", NONE},
false, false, false, false }, // Flags must be correctly set when using block scoping.
{ "if (1) { return function () { while (true) new this() } }", {"\"use strict\"; while (true) { let x; this, arguments; }",
false, false, false, false }, INNER_ARGUMENTS | INNER_THIS},
{ "return function (x) { return () => this }", {"\"use strict\"; while (true) { let x; this, super(), arguments; }",
false, false, false, false }, INNER_ARGUMENTS | INNER_SUPER | INNER_THIS},
// Flags must be correctly set when using block scoping. {"\"use strict\"; if (foo()) { let x; this.f() }", INNER_THIS},
{ "\"use strict\"; while (true) { let x; this, arguments; }", {"\"use strict\"; if (foo()) { let x; super.f() }", INNER_SUPER},
false, false, true, true }, {"\"use strict\"; if (1) {"
{ "\"use strict\"; if (foo()) { let x; this.f() }", " let x; return function () { return this + super() + arguments }"
false, false, true, false }, "}",
{ "\"use strict\"; if (1) {" NONE},
" let x; return function () { return this + arguments }" };
"}",
false, false, false, false },
};
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory(); i::Factory* factory = isolate->factory();
...@@ -1013,6 +1017,7 @@ TEST(ScopeUsesThisAndArguments) { ...@@ -1013,6 +1017,7 @@ TEST(ScopeUsesThisAndArguments) {
isolate->unicode_cache()}; isolate->unicode_cache()};
i::Parser parser(&info, &parse_info); i::Parser parser(&info, &parse_info);
parser.set_allow_arrow_functions(true); parser.set_allow_arrow_functions(true);
parser.set_allow_classes(true);
parser.set_allow_harmony_scoping(true); parser.set_allow_harmony_scoping(true);
info.MarkAsGlobal(); info.MarkAsGlobal();
parser.Parse(); parser.Parse();
...@@ -1025,11 +1030,16 @@ TEST(ScopeUsesThisAndArguments) { ...@@ -1025,11 +1030,16 @@ TEST(ScopeUsesThisAndArguments) {
CHECK_EQ(1, global_scope->inner_scopes()->length()); CHECK_EQ(1, global_scope->inner_scopes()->length());
i::Scope* scope = global_scope->inner_scopes()->at(0); i::Scope* scope = global_scope->inner_scopes()->at(0);
CHECK_EQ(source_data[i].uses_this, scope->uses_this()); CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
CHECK_EQ(source_data[i].uses_arguments, scope->uses_arguments()); scope->uses_arguments());
CHECK_EQ(source_data[i].inner_uses_this, scope->inner_uses_this()); CHECK_EQ((source_data[i].expected & SUPER) != 0, scope->uses_super());
CHECK_EQ(source_data[i].inner_uses_arguments, CHECK_EQ((source_data[i].expected & THIS) != 0, scope->uses_this());
CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0,
scope->inner_uses_arguments()); scope->inner_uses_arguments());
CHECK_EQ((source_data[i].expected & INNER_SUPER) != 0,
scope->inner_uses_super());
CHECK_EQ((source_data[i].expected & INNER_THIS) != 0,
scope->inner_uses_this());
} }
} }
} }
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-classes --allow-natives-syntax
(function TestHomeObject() {
var object = {
method() {
return super.method();
},
get getter() {
return super.getter;
},
set setter(v) {
super.setter = v;
},
get accessor() {
return super.accessor;
},
set accessor(v) {
super.accessor = v;
},
property: function() {
super.property();
},
propertyWithParen: (function() {
super.property();
}),
propertyWithParens: ((function() {
super.property();
})),
methodNoSuper() {},
get getterNoSuper() {},
set setterNoSuper(v) {},
get accessorNoSuper() {},
set accessorNoSuper(v) {},
propertyNoSuper: function() {},
propertyWithParenNoSuper: (function() {}),
propertyWithParensNoSuper: ((function() {}))
};
assertEquals(object, object.method[%HomeObjectSymbol()]);
var desc = Object.getOwnPropertyDescriptor(object, 'getter');
assertEquals(object, desc.get[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'setter');
assertEquals(object, desc.set[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'accessor');
assertEquals(object, desc.get[%HomeObjectSymbol()]);
assertEquals(object, desc.set[%HomeObjectSymbol()]);
assertEquals(object, object.property[%HomeObjectSymbol()]);
assertEquals(object, object.propertyWithParen[%HomeObjectSymbol()]);
assertEquals(object, object.propertyWithParens[%HomeObjectSymbol()]);
assertEquals(undefined, object.methodNoSuper[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'getterNoSuper');
assertEquals(undefined, desc.get[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'setterNoSuper');
assertEquals(undefined, desc.set[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'accessorNoSuper');
assertEquals(undefined, desc.get[%HomeObjectSymbol()]);
assertEquals(undefined, desc.set[%HomeObjectSymbol()]);
assertEquals(undefined, object.propertyNoSuper[%HomeObjectSymbol()]);
assertEquals(undefined, object.propertyWithParenNoSuper[%HomeObjectSymbol()]);
assertEquals(undefined,
object.propertyWithParensNoSuper[%HomeObjectSymbol()]);
})();
(function TestMethod() {
var object = {
__proto__: {
method(x) {
return 'proto' + x;
}
},
method(x) {
return super.method(x);
}
};
assertEquals('proto42', object.method(42));
})();
(function TestGetter() {
var object = {
__proto__: {
_x: 42,
get x() {
return 'proto' + this._x;
}
},
get x() {
return super.x;
}
};
assertEquals('proto42', object.x);
})();
(function TestSetter() {
var object = {
__proto__: {
_x: 0,
set x(v) {
return this._x = v;
}
},
set x(v) {
super.x = v;
}
};
assertEquals(1, object.x = 1);
assertEquals(1, object._x);
assertEquals(0, Object.getPrototypeOf(object)._x);
})();
(function TestMethodAsProperty() {
var object = {
__proto__: {
method: function(x) {
return 'proto' + x;
}
},
method: function(x) {
return super.method(x);
}
};
assertEquals('proto42', object.method(42));
})();
(function TestOptimized() {
// Object literals without any accessors get optimized.
var object = {
method() {
return super.toString;
}
};
assertEquals(Object.prototype.toString, object.method());
})();
(function TestConciseGenerator() {
var o = {
__proto__: {
m() {
return 42;
}
},
*g() {
yield super.m();
},
g2: function*() {
yield super.m() + 1;
},
g3: (function*() {
yield super.m() + 2;
})
};
assertEquals(42, o.g().next().value);
assertEquals(43, o.g2().next().value);
assertEquals(44, o.g3().next().value);
})();
...@@ -124,6 +124,9 @@ ...@@ -124,6 +124,9 @@
'regress/regress-crbug-259300': [PASS, NO_VARIANTS], 'regress/regress-crbug-259300': [PASS, NO_VARIANTS],
'regress/regress-frame-details-null-receiver': [PASS, NO_VARIANTS], 'regress/regress-frame-details-null-receiver': [PASS, NO_VARIANTS],
# TODO(arv): TurboFan does not yet add [[HomeObject]] as needed.
'harmony/object-literals-super': [PASS, NO_VARIANTS],
############################################################################## ##############################################################################
# Too slow in debug mode with --stress-opt mode. # Too slow in debug mode with --stress-opt mode.
'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]], 'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment