Commit 815f91c0 authored by henrique.ferreiro's avatar henrique.ferreiro Committed by Commit bot

[es6] Perform the IsConstructor test in GetSuperConstructor.

This is so that a NotSuperConstructor error is thrown before evaluating the
arguments to the super constructor. Besides updating the runtime function, a
new bytecode GetSuperConstructor is introduced.

BUG=v8:5336

Review-Url: https://codereview.chromium.org/2504553003
Cr-Commit-Position: refs/heads/master@{#41788}
parent b695c388
...@@ -1078,5 +1078,17 @@ void Builtins::Generate_OrdinaryHasInstance( ...@@ -1078,5 +1078,17 @@ void Builtins::Generate_OrdinaryHasInstance(
assembler.Return(assembler.OrdinaryHasInstance(context, constructor, object)); assembler.Return(assembler.OrdinaryHasInstance(context, constructor, object));
} }
void Builtins::Generate_GetSuperConstructor(
compiler::CodeAssemblerState* state) {
typedef compiler::Node Node;
typedef TypeofDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* object = assembler.Parameter(Descriptor::kObject);
Node* context = assembler.Parameter(Descriptor::kContext);
assembler.Return(assembler.GetSuperConstructor(object, context));
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -179,6 +179,7 @@ namespace internal { ...@@ -179,6 +179,7 @@ namespace internal {
TFS(ToInteger, BUILTIN, kNoExtraICState, TypeConversion) \ TFS(ToInteger, BUILTIN, kNoExtraICState, TypeConversion) \
TFS(ToLength, BUILTIN, kNoExtraICState, TypeConversion) \ TFS(ToLength, BUILTIN, kNoExtraICState, TypeConversion) \
TFS(Typeof, BUILTIN, kNoExtraICState, Typeof) \ TFS(Typeof, BUILTIN, kNoExtraICState, Typeof) \
TFS(GetSuperConstructor, BUILTIN, kNoExtraICState, TypeConversion) \
\ \
/* Handlers */ \ /* Handlers */ \
TFS(KeyedLoadIC_Megamorphic_TF, KEYED_LOAD_IC, kNoExtraICState, \ TFS(KeyedLoadIC_Megamorphic_TF, KEYED_LOAD_IC, kNoExtraICState, \
......
...@@ -251,6 +251,7 @@ TFS_BUILTIN(ForInFilter) ...@@ -251,6 +251,7 @@ TFS_BUILTIN(ForInFilter)
TFS_BUILTIN(NewUnmappedArgumentsElements) TFS_BUILTIN(NewUnmappedArgumentsElements)
TFS_BUILTIN(NewRestParameterElements) TFS_BUILTIN(NewRestParameterElements)
TFS_BUILTIN(PromiseHandleReject) TFS_BUILTIN(PromiseHandleReject)
TFS_BUILTIN(GetSuperConstructor)
#undef TFS_BUILTIN #undef TFS_BUILTIN
......
...@@ -128,6 +128,7 @@ class V8_EXPORT_PRIVATE CodeFactory final { ...@@ -128,6 +128,7 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable SubString(Isolate* isolate); static Callable SubString(Isolate* isolate);
static Callable Typeof(Isolate* isolate); static Callable Typeof(Isolate* isolate);
static Callable GetSuperConstructor(Isolate* isolate);
static Callable FastCloneRegExp(Isolate* isolate); static Callable FastCloneRegExp(Isolate* isolate);
static Callable FastCloneShallowArray(Isolate* isolate); static Callable FastCloneShallowArray(Isolate* isolate);
......
...@@ -2896,6 +2896,13 @@ Node* CodeStubAssembler::IsCallableMap(Node* map) { ...@@ -2896,6 +2896,13 @@ Node* CodeStubAssembler::IsCallableMap(Node* map) {
Int32Constant(0)); Int32Constant(0));
} }
Node* CodeStubAssembler::IsConstructorMap(Node* map) {
CSA_ASSERT(this, IsMap(map));
return Word32NotEqual(
Word32And(LoadMapBitField(map), Int32Constant(1 << Map::kIsConstructor)),
Int32Constant(0));
}
Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) { Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) {
STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
return Int32LessThanOrEqual(instance_type, return Int32LessThanOrEqual(instance_type,
...@@ -2992,6 +2999,10 @@ Node* CodeStubAssembler::IsUnseededNumberDictionary(Node* object) { ...@@ -2992,6 +2999,10 @@ Node* CodeStubAssembler::IsUnseededNumberDictionary(Node* object) {
LoadRoot(Heap::kUnseededNumberDictionaryMapRootIndex)); LoadRoot(Heap::kUnseededNumberDictionaryMapRootIndex));
} }
Node* CodeStubAssembler::IsJSFunction(Node* object) {
return HasInstanceType(object, JS_FUNCTION_TYPE);
}
Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) { Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) {
CSA_ASSERT(this, IsString(string)); CSA_ASSERT(this, IsString(string));
// Translate the {index} into a Word. // Translate the {index} into a Word.
...@@ -7846,6 +7857,32 @@ Node* CodeStubAssembler::Typeof(Node* value, Node* context) { ...@@ -7846,6 +7857,32 @@ Node* CodeStubAssembler::Typeof(Node* value, Node* context) {
return result_var.value(); return result_var.value();
} }
Node* CodeStubAssembler::GetSuperConstructor(Node* active_function,
Node* context) {
CSA_ASSERT(this, IsJSFunction(active_function));
Label is_not_constructor(this, Label::kDeferred), out(this);
Variable result(this, MachineRepresentation::kTagged);
Node* map = LoadMap(active_function);
Node* prototype = LoadMapPrototype(map);
Node* prototype_map = LoadMap(prototype);
GotoUnless(IsConstructorMap(prototype_map), &is_not_constructor);
result.Bind(prototype);
Goto(&out);
Bind(&is_not_constructor);
{
result.Bind(CallRuntime(Runtime::kThrowNotSuperConstructor, context,
prototype, active_function));
Goto(&out);
}
Bind(&out);
return result.value();
}
Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable, Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable,
Node* context) { Node* context) {
Label return_runtime(this, Label::kDeferred), end(this); Label return_runtime(this, Label::kDeferred), end(this);
......
...@@ -658,6 +658,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -658,6 +658,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsHashTable(Node* object); Node* IsHashTable(Node* object);
Node* IsDictionary(Node* object); Node* IsDictionary(Node* object);
Node* IsUnseededNumberDictionary(Node* object); Node* IsUnseededNumberDictionary(Node* object);
Node* IsConstructorMap(Node* map);
Node* IsJSFunction(Node* object);
// ElementsKind helpers: // ElementsKind helpers:
Node* IsFastElementsKind(Node* elements_kind); Node* IsFastElementsKind(Node* elements_kind);
...@@ -1078,6 +1080,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1078,6 +1080,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* Typeof(Node* value, Node* context); Node* Typeof(Node* value, Node* context);
Node* GetSuperConstructor(Node* value, Node* context);
Node* InstanceOf(Node* object, Node* callable, Node* context); Node* InstanceOf(Node* object, Node* callable, Node* context);
// Debug helpers // Debug helpers
......
...@@ -1626,6 +1626,13 @@ void BytecodeGraphBuilder::VisitDeletePropertySloppy() { ...@@ -1626,6 +1626,13 @@ void BytecodeGraphBuilder::VisitDeletePropertySloppy() {
BuildDelete(LanguageMode::SLOPPY); BuildDelete(LanguageMode::SLOPPY);
} }
void BytecodeGraphBuilder::VisitGetSuperConstructor() {
Node* node = NewNode(javascript()->GetSuperConstructor(),
environment()->LookupAccumulator());
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node,
Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) { void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Node* left = Node* left =
......
...@@ -273,6 +273,12 @@ void JSGenericLowering::LowerJSDeleteProperty(Node* node) { ...@@ -273,6 +273,12 @@ void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
: Runtime::kDeleteProperty_Sloppy); : Runtime::kDeleteProperty_Sloppy);
} }
void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable = CodeFactory::GetSuperConstructor(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSInstanceOf(Node* node) { void JSGenericLowering::LowerJSInstanceOf(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node); CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable = CodeFactory::InstanceOf(isolate()); Callable callable = CodeFactory::InstanceOf(isolate());
......
...@@ -480,6 +480,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) { ...@@ -480,6 +480,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(StoreMessage, Operator::kNoThrow, 1, 0) \ V(StoreMessage, Operator::kNoThrow, 1, 0) \
V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \ V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \
V(StackCheck, Operator::kNoWrite, 0, 0) \ V(StackCheck, Operator::kNoWrite, 0, 0) \
V(GetSuperConstructor, Operator::kNoWrite, 1, 1) \
V(StoreDataPropertyInLiteral, Operator::kNoProperties, 5, 0) V(StoreDataPropertyInLiteral, Operator::kNoProperties, 5, 0)
#define BINARY_OP_LIST(V) \ #define BINARY_OP_LIST(V) \
......
...@@ -521,6 +521,8 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final ...@@ -521,6 +521,8 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* HasProperty(); const Operator* HasProperty();
const Operator* GetSuperConstructor();
const Operator* LoadGlobal(const Handle<Name>& name, const Operator* LoadGlobal(const Handle<Name>& name,
const VectorSlotPair& feedback, const VectorSlotPair& feedback,
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF); TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
......
...@@ -151,7 +151,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) { ...@@ -151,7 +151,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
case Runtime::kDefineGetterPropertyUnchecked: // TODO(jarin): Is it safe? case Runtime::kDefineGetterPropertyUnchecked: // TODO(jarin): Is it safe?
case Runtime::kDefineSetterPropertyUnchecked: // TODO(jarin): Is it safe? case Runtime::kDefineSetterPropertyUnchecked: // TODO(jarin): Is it safe?
case Runtime::kGeneratorGetContinuation: case Runtime::kGeneratorGetContinuation:
case Runtime::kGetSuperConstructor:
case Runtime::kIsFunction: case Runtime::kIsFunction:
case Runtime::kNewClosure: case Runtime::kNewClosure:
case Runtime::kNewClosure_Tenured: case Runtime::kNewClosure_Tenured:
...@@ -178,7 +177,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) { ...@@ -178,7 +177,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
case Runtime::kInlineGeneratorClose: case Runtime::kInlineGeneratorClose:
case Runtime::kInlineGeneratorGetInputOrDebugPos: case Runtime::kInlineGeneratorGetInputOrDebugPos:
case Runtime::kInlineGeneratorGetResumeMode: case Runtime::kInlineGeneratorGetResumeMode:
case Runtime::kInlineGetSuperConstructor:
case Runtime::kInlineIsArray: case Runtime::kInlineIsArray:
case Runtime::kInlineIsJSReceiver: case Runtime::kInlineIsJSReceiver:
case Runtime::kInlineIsRegExp: case Runtime::kInlineIsRegExp:
......
...@@ -144,7 +144,8 @@ ...@@ -144,7 +144,8 @@
V(JSStoreGlobal) \ V(JSStoreGlobal) \
V(JSStoreDataPropertyInLiteral) \ V(JSStoreDataPropertyInLiteral) \
V(JSDeleteProperty) \ V(JSDeleteProperty) \
V(JSHasProperty) V(JSHasProperty) \
V(JSGetSuperConstructor)
#define JS_CONTEXT_OP_LIST(V) \ #define JS_CONTEXT_OP_LIST(V) \
V(JSLoadContext) \ V(JSLoadContext) \
......
...@@ -102,6 +102,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) { ...@@ -102,6 +102,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSForInNext: case IrOpcode::kJSForInNext:
case IrOpcode::kJSForInPrepare: case IrOpcode::kJSForInPrepare:
case IrOpcode::kJSStackCheck: case IrOpcode::kJSStackCheck:
case IrOpcode::kJSGetSuperConstructor:
return true; return true;
default: default:
......
...@@ -1259,6 +1259,10 @@ Type* Typer::Visitor::JSOrdinaryHasInstanceTyper(Type* lhs, Type* rhs, ...@@ -1259,6 +1259,10 @@ Type* Typer::Visitor::JSOrdinaryHasInstanceTyper(Type* lhs, Type* rhs,
return Type::Boolean(); return Type::Boolean();
} }
Type* Typer::Visitor::TypeJSGetSuperConstructor(Node* node) {
return Type::Callable();
}
// JS context operators. // JS context operators.
......
...@@ -640,6 +640,13 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -640,6 +640,13 @@ void Verifier::Visitor::Check(Node* node) {
// Type is String. // Type is String.
CheckTypeIs(node, Type::String()); CheckTypeIs(node, Type::String());
break; break;
case IrOpcode::kJSGetSuperConstructor:
// We don't check the input for Type::Function because
// this_function can be context-allocated.
// Any -> Callable.
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Callable());
break;
case IrOpcode::kJSLoadContext: case IrOpcode::kJSLoadContext:
// Type can be anything. // Type can be anything.
......
...@@ -324,6 +324,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { ...@@ -324,6 +324,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
OutputGetSuperConstructor(out);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
Token::Value op, Register reg, int feedback_slot) { Token::Value op, Register reg, int feedback_slot) {
switch (op) { switch (op) {
......
...@@ -259,6 +259,11 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -259,6 +259,11 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
BytecodeArrayBuilder& LogicalNot(); BytecodeArrayBuilder& LogicalNot();
BytecodeArrayBuilder& TypeOf(); BytecodeArrayBuilder& TypeOf();
// Expects a heap object in the accumulator. Returns its super constructor in
// the register |out| if it passes the IsConstructor test. Otherwise, it
// throws a TypeError exception.
BytecodeArrayBuilder& GetSuperConstructor(Register out);
// Deletes property from an object. This expects that accumulator contains // Deletes property from an object. This expects that accumulator contains
// the key to be deleted and the register contains a reference to the object. // the key to be deleted and the register contains a reference to the object.
BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode); BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
......
...@@ -2513,11 +2513,9 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) { ...@@ -2513,11 +2513,9 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
SuperCallReference* super = expr->expression()->AsSuperCallReference(); SuperCallReference* super = expr->expression()->AsSuperCallReference();
// Prepare the constructor to the super call. // Prepare the constructor to the super call.
Register this_function = VisitForRegisterValue(super->this_function_var()); VisitForAccumulatorValue(super->this_function_var());
builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); Register constructor = register_allocator()->NewRegister();
builder()->GetSuperConstructor(constructor);
Register constructor = this_function; // Re-use dead this_function register.
builder()->StoreAccumulatorInRegister(constructor);
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
......
...@@ -143,6 +143,9 @@ namespace interpreter { ...@@ -143,6 +143,9 @@ namespace interpreter {
V(DeletePropertyStrict, AccumulatorUse::kReadWrite, OperandType::kReg) \ V(DeletePropertyStrict, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(DeletePropertySloppy, AccumulatorUse::kReadWrite, OperandType::kReg) \ V(DeletePropertySloppy, AccumulatorUse::kReadWrite, OperandType::kReg) \
\ \
/* GetSuperConstructor operator */ \
V(GetSuperConstructor, AccumulatorUse::kRead, OperandType::kRegOut) \
\
/* Call operations */ \ /* Call operations */ \
V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kRegList, \ V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kRegList, \
OperandType::kRegCount, OperandType::kIdx) \ OperandType::kRegCount, OperandType::kIdx) \
......
...@@ -1675,6 +1675,19 @@ void Interpreter::DoDeletePropertySloppy(InterpreterAssembler* assembler) { ...@@ -1675,6 +1675,19 @@ void Interpreter::DoDeletePropertySloppy(InterpreterAssembler* assembler) {
DoDelete(Runtime::kDeleteProperty_Sloppy, assembler); DoDelete(Runtime::kDeleteProperty_Sloppy, assembler);
} }
// GetSuperConstructor
//
// Get the super constructor from the object referenced by the accumulator.
// The result is stored in register |reg|.
void Interpreter::DoGetSuperConstructor(InterpreterAssembler* assembler) {
Node* active_function = __ GetAccumulator();
Node* context = __ GetContext();
Node* result = __ GetSuperConstructor(active_function, context);
Node* reg = __ BytecodeOperandReg(0);
__ StoreRegister(result, reg);
__ Dispatch();
}
void Interpreter::DoJSCall(InterpreterAssembler* assembler, void Interpreter::DoJSCall(InterpreterAssembler* assembler,
TailCallMode tail_call_mode) { TailCallMode tail_call_mode) {
Node* function_reg = __ BytecodeOperandReg(0); Node* function_reg = __ BytecodeOperandReg(0);
......
...@@ -342,7 +342,9 @@ class ErrorUtils : public AllStatic { ...@@ -342,7 +342,9 @@ class ErrorUtils : public AllStatic {
T(NotIterable, "% is not iterable") \ T(NotIterable, "% is not iterable") \
T(NotPropertyName, "% is not a valid property name") \ T(NotPropertyName, "% is not a valid property name") \
T(NotTypedArray, "this is not a typed array.") \ T(NotTypedArray, "this is not a typed array.") \
T(NotSharedTypedArray, "% is not a shared typed array.") \ T(NotSuperConstructor, "Super constructor % of % is not a constructor") \
T(NotSuperConstructorAnonymousClass, \
"Super constructor % of anonymous class is not a constructor") \
T(NotIntegerSharedTypedArray, "% is not an integer shared typed array.") \ T(NotIntegerSharedTypedArray, "% is not an integer shared typed array.") \
T(NotInt32SharedTypedArray, "% is not an int32 shared typed array.") \ T(NotInt32SharedTypedArray, "% is not an int32 shared typed array.") \
T(ObjectGetterExpectingFunction, \ T(ObjectGetterExpectingFunction, \
......
...@@ -27,7 +27,6 @@ RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) { ...@@ -27,7 +27,6 @@ RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
isolate, NewReferenceError(MessageTemplate::kNonMethod)); isolate, NewReferenceError(MessageTemplate::kNonMethod));
} }
RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) { RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 0); DCHECK(args.length() == 0);
...@@ -60,6 +59,47 @@ RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) { ...@@ -60,6 +59,47 @@ RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
isolate, NewTypeError(MessageTemplate::kStaticPrototype)); isolate, NewTypeError(MessageTemplate::kStaticPrototype));
} }
namespace {
Object* ThrowNotSuperConstructor(Isolate* isolate, Handle<Object> constructor,
Handle<JSFunction> function) {
Handle<Object> super_name;
if (constructor->IsJSFunction()) {
super_name = handle(Handle<JSFunction>::cast(constructor)->shared()->name(),
isolate);
} else if (constructor->IsOddball()) {
DCHECK(constructor->IsNull(isolate));
super_name = isolate->factory()->null_string();
} else {
super_name = Object::NoSideEffectsToString(isolate, constructor);
}
// null constructor
if (Handle<String>::cast(super_name)->length() == 0) {
super_name = isolate->factory()->null_string();
}
Handle<Object> function_name(function->shared()->name(), isolate);
// anonymous class
if (Handle<String>::cast(function_name)->length() == 0) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(MessageTemplate::kNotSuperConstructorAnonymousClass,
super_name));
}
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kNotSuperConstructor, super_name,
function_name));
}
} // namespace
RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
return ThrowNotSuperConstructor(isolate, constructor, function);
}
RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) { RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
DCHECK(args.length() == 0); DCHECK(args.length() == 0);
return isolate->heap()->home_object_symbol(); return isolate->heap()->home_object_symbol();
...@@ -422,8 +462,14 @@ RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) { ...@@ -422,8 +462,14 @@ RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper_Sloppy) {
RUNTIME_FUNCTION(Runtime_GetSuperConstructor) { RUNTIME_FUNCTION(Runtime_GetSuperConstructor) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(JSFunction, active_function, 0); CONVERT_ARG_HANDLE_CHECKED(JSFunction, active_function, 0);
return active_function->map()->prototype(); Object* prototype = active_function->map()->prototype();
if (!prototype->IsConstructor()) {
return ThrowNotSuperConstructor(
isolate, Handle<JSFunction>::cast(handle(prototype, isolate)),
active_function);
}
return prototype;
} }
RUNTIME_FUNCTION(Runtime_NewWithSpread) { RUNTIME_FUNCTION(Runtime_NewWithSpread) {
......
...@@ -80,6 +80,7 @@ namespace internal { ...@@ -80,6 +80,7 @@ namespace internal {
F(ThrowConstructorNonCallableError, 1, 1) \ F(ThrowConstructorNonCallableError, 1, 1) \
F(ThrowArrayNotSubclassableError, 0, 1) \ F(ThrowArrayNotSubclassableError, 0, 1) \
F(ThrowStaticPrototypeError, 0, 1) \ F(ThrowStaticPrototypeError, 0, 1) \
F(ThrowNotSuperConstructor, 2, 1) \
F(HomeObjectSymbol, 0, 1) \ F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 4, 1) \ F(DefineClass, 4, 1) \
F(InstallClassNameAccessor, 1, 1) \ F(InstallClassNameAccessor, 1, 1) \
......
...@@ -107,14 +107,14 @@ snippet: " ...@@ -107,14 +107,14 @@ snippet: "
" "
frame size: 4 frame size: 4
parameter count: 1 parameter count: 1
bytecode array length: 82 bytecode array length: 79
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
B(Ldar), R(new_target), B(Ldar), R(new_target),
/* 113 E> */ B(StackCheck), /* 113 E> */ B(StackCheck),
/* 118 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), /* 118 S> */ B(Ldar), R(1),
B(Star), R(2), B(GetSuperConstructor), R(2),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(3), B(Star), R(3),
B(Ldar), R(0), B(Ldar), R(0),
...@@ -164,14 +164,14 @@ snippet: " ...@@ -164,14 +164,14 @@ snippet: "
" "
frame size: 4 frame size: 4
parameter count: 1 parameter count: 1
bytecode array length: 78 bytecode array length: 75
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
B(Ldar), R(new_target), B(Ldar), R(new_target),
/* 112 E> */ B(StackCheck), /* 112 E> */ B(StackCheck),
/* 117 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), /* 117 S> */ B(Ldar), R(1),
B(Star), R(2), B(GetSuperConstructor), R(2),
B(Ldar), R(0), B(Ldar), R(0),
/* 117 E> */ B(New), R(2), R(0), U8(0), U8(2), /* 117 E> */ B(New), R(2), R(0), U8(0), U8(2),
B(Star), R(2), B(Star), R(2),
......
...@@ -88,7 +88,7 @@ bytecodes: [ ...@@ -88,7 +88,7 @@ bytecodes: [
B(TestEqualStrict), R(12), U8(20), B(TestEqualStrict), R(12), U8(20),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(130), B(Wide), B(LdaSmi), U16(131),
B(Star), R(12), B(Star), R(12),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(13), B(Star), R(13),
...@@ -233,7 +233,7 @@ bytecodes: [ ...@@ -233,7 +233,7 @@ bytecodes: [
B(TestEqualStrict), R(13), U8(20), B(TestEqualStrict), R(13), U8(20),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(130), B(Wide), B(LdaSmi), U16(131),
B(Star), R(13), B(Star), R(13),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(14), B(Star), R(14),
...@@ -391,7 +391,7 @@ bytecodes: [ ...@@ -391,7 +391,7 @@ bytecodes: [
B(TestEqualStrict), R(12), U8(22), B(TestEqualStrict), R(12), U8(22),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(130), B(Wide), B(LdaSmi), U16(131),
B(Star), R(12), B(Star), R(12),
B(LdaConstant), U8(9), B(LdaConstant), U8(9),
B(Star), R(13), B(Star), R(13),
...@@ -539,7 +539,7 @@ bytecodes: [ ...@@ -539,7 +539,7 @@ bytecodes: [
B(TestEqualStrict), R(11), U8(24), B(TestEqualStrict), R(11), U8(24),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(130), B(Wide), B(LdaSmi), U16(131),
B(Star), R(11), B(Star), R(11),
B(LdaConstant), U8(11), B(LdaConstant), U8(11),
B(Star), R(12), B(Star), R(12),
......
...@@ -491,7 +491,7 @@ bytecodes: [ ...@@ -491,7 +491,7 @@ bytecodes: [
B(TestEqualStrict), R(10), U8(20), B(TestEqualStrict), R(10), U8(20),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(18), B(Jump), U8(18),
B(Wide), B(LdaSmi), U16(130), B(Wide), B(LdaSmi), U16(131),
B(Star), R(10), B(Star), R(10),
B(LdaConstant), U8(14), B(LdaConstant), U8(14),
B(Star), R(11), B(Star), R(11),
......
...@@ -19,7 +19,7 @@ snippet: " ...@@ -19,7 +19,7 @@ snippet: "
" "
frame size: 7 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 32 bytecode array length: 29
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(2), B(Star), R(2),
...@@ -27,8 +27,8 @@ bytecodes: [ ...@@ -27,8 +27,8 @@ bytecodes: [
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
B(Ldar), R(new_target), B(Ldar), R(new_target),
/* 93 E> */ B(StackCheck), /* 93 E> */ B(StackCheck),
/* 93 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), /* 93 S> */ B(Ldar), R(1),
B(Star), R(3), B(GetSuperConstructor), R(3),
B(Mov), R(3), R(4), B(Mov), R(3), R(4),
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
B(Mov), R(2), R(6), B(Mov), R(2), R(6),
...@@ -55,7 +55,7 @@ snippet: " ...@@ -55,7 +55,7 @@ snippet: "
" "
frame size: 8 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 69 bytecode array length: 66
bytecodes: [ bytecodes: [
B(CreateRestParameter), B(CreateRestParameter),
B(Star), R(2), B(Star), R(2),
...@@ -63,8 +63,8 @@ bytecodes: [ ...@@ -63,8 +63,8 @@ bytecodes: [
B(Mov), R(new_target), R(0), B(Mov), R(new_target), R(0),
B(Ldar), R(new_target), B(Ldar), R(new_target),
/* 128 E> */ B(StackCheck), /* 128 E> */ B(StackCheck),
/* 140 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), /* 140 S> */ B(Ldar), R(1),
B(Star), R(3), B(GetSuperConstructor), R(3),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
B(Star), R(6), B(Star), R(6),
B(Mov), R(3), R(4), B(Mov), R(3), R(4),
......
...@@ -415,9 +415,6 @@ ...@@ -415,9 +415,6 @@
'annexB/language/eval-code/direct/func-switch-case-eval-func-no-skip-try': [FAIL], 'annexB/language/eval-code/direct/func-switch-case-eval-func-no-skip-try': [FAIL],
'annexB/language/eval-code/direct/func-switch-dflt-eval-func-no-skip-try': [FAIL], 'annexB/language/eval-code/direct/func-switch-dflt-eval-func-no-skip-try': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5336
'language/expressions/super/call-proto-not-ctor': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5546 # https://bugs.chromium.org/p/v8/issues/detail?id=5546
'language/expressions/tagged-template/invalid-escape-sequences': [FAIL], 'language/expressions/tagged-template/invalid-escape-sequences': [FAIL],
......
...@@ -213,6 +213,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -213,6 +213,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.ConvertAccumulatorToObject(reg) .ConvertAccumulatorToObject(reg)
.ConvertAccumulatorToName(reg); .ConvertAccumulatorToName(reg);
// Emit GetSuperConstructor.
builder.GetSuperConstructor(reg);
// Short jumps with Imm8 operands // Short jumps with Imm8 operands
{ {
BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4, BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4,
......
...@@ -9,7 +9,7 @@ PASS new B did not throw exception. ...@@ -9,7 +9,7 @@ PASS new B did not throw exception.
PASS B() threw exception TypeError: Class constructor B cannot be invoked without 'new'. PASS B() threw exception TypeError: Class constructor B cannot be invoked without 'new'.
PASS new (class { constructor() {} })() did not throw exception. PASS new (class { constructor() {} })() did not throw exception.
PASS (class { constructor() {} })() threw exception TypeError: Class constructor cannot be invoked without 'new'. PASS (class { constructor() {} })() threw exception TypeError: Class constructor cannot be invoked without 'new'.
PASS new (class extends null { constructor() { super() } })() threw exception TypeError: super is not a constructor. PASS new (class extends null { constructor() { super() } })() threw exception TypeError: Super constructor null of anonymous class is not a constructor.
PASS (class extends null { constructor() { super() } })() threw exception TypeError: Class constructor cannot be invoked without 'new'. PASS (class extends null { constructor() { super() } })() threw exception TypeError: Class constructor cannot be invoked without 'new'.
PASS successfullyParsed is true PASS successfullyParsed is true
......
...@@ -32,7 +32,7 @@ shouldNotThrow('new B'); ...@@ -32,7 +32,7 @@ shouldNotThrow('new B');
shouldThrow('B()', '"TypeError: Class constructor B cannot be invoked without \'new\'"'); shouldThrow('B()', '"TypeError: Class constructor B cannot be invoked without \'new\'"');
shouldNotThrow('new (class { constructor() {} })()'); shouldNotThrow('new (class { constructor() {} })()');
shouldThrow('(class { constructor() {} })()', '"TypeError: Class constructor cannot be invoked without \'new\'"'); shouldThrow('(class { constructor() {} })()', '"TypeError: Class constructor cannot be invoked without \'new\'"');
shouldThrow('new (class extends null { constructor() { super() } })()', '"TypeError: super is not a constructor"'); shouldThrow('new (class extends null { constructor() { super() } })()', '"TypeError: Super constructor null of anonymous class is not a constructor"');
shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Class constructor cannot be invoked without \'new\'"'); shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Class constructor cannot be invoked without \'new\'"');
var successfullyParsed = true; var successfullyParsed = true;
...@@ -60,7 +60,7 @@ PASS x = {}; new (class extends undefined { constructor () { return x; } }) thre ...@@ -60,7 +60,7 @@ PASS x = {}; new (class extends undefined { constructor () { return x; } }) thre
PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a constructor or null. PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined. PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined.
PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: super is not a constructor. PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: Super constructor null of anonymous class is not a constructor.
PASS x = {}; new (class extends null { constructor () { return x } }) is x PASS x = {}; new (class extends null { constructor () { return x } }) is x
PASS y = 12; new (class extends null { constructor () { return y; } }) threw exception TypeError: Derived constructors may only return object or undefined. PASS y = 12; new (class extends null { constructor () { return y; } }) threw exception TypeError: Derived constructors may only return object or undefined.
PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
......
...@@ -98,7 +98,7 @@ shouldThrow('x = {}; new (class extends undefined { constructor () { return x; } ...@@ -98,7 +98,7 @@ shouldThrow('x = {}; new (class extends undefined { constructor () { return x; }
shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Class extends value undefined is not a constructor or null"'); shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Class extends value undefined is not a constructor or null"');
shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x'); shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
shouldThrow('new (class extends null { constructor () { this; } })', '"ReferenceError: this is not defined"'); shouldThrow('new (class extends null { constructor () { this; } })', '"ReferenceError: this is not defined"');
shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: super is not a constructor"'); shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: Super constructor null of anonymous class is not a constructor"');
shouldBe('x = {}; new (class extends null { constructor () { return x } })', 'x'); shouldBe('x = {}; new (class extends null { constructor () { return x } })', 'x');
shouldThrow('y = 12; new (class extends null { constructor () { return y; } })', '"TypeError: Derived constructors may only return object or undefined"'); shouldThrow('y = 12; new (class extends null { constructor () { return y; } })', '"TypeError: Derived constructors may only return object or undefined"');
shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x'); shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
......
...@@ -29,12 +29,12 @@ PASS x instanceof Base is false ...@@ -29,12 +29,12 @@ PASS x instanceof Base is false
PASS new (class extends Base { constructor() { } }) threw exception ReferenceError: this is not defined. PASS new (class extends Base { constructor() { } }) threw exception ReferenceError: this is not defined.
PASS new (class extends Base { constructor() { return 1; } }) threw exception TypeError: Derived constructors may only return object or undefined. PASS new (class extends Base { constructor() { return 1; } }) threw exception TypeError: Derived constructors may only return object or undefined.
PASS new (class extends null { constructor() { return undefined } }) threw exception ReferenceError: this is not defined. PASS new (class extends null { constructor() { return undefined } }) threw exception ReferenceError: this is not defined.
PASS new (class extends null { constructor() { super(); return undefined } }) threw exception TypeError: super is not a constructor. PASS new (class extends null { constructor() { super(); return undefined } }) threw exception TypeError: Super constructor null of anonymous class is not a constructor.
PASS x = { }; new (class extends null { constructor() { return x } }); is x PASS x = { }; new (class extends null { constructor() { return x } }); is x
PASS x instanceof Object is true PASS x instanceof Object is true
PASS new (class extends null { constructor() { } }) threw exception ReferenceError: this is not defined. PASS new (class extends null { constructor() { } }) threw exception ReferenceError: this is not defined.
PASS new (class extends null { constructor() { return 1; } }) threw exception TypeError: Derived constructors may only return object or undefined. PASS new (class extends null { constructor() { return 1; } }) threw exception TypeError: Derived constructors may only return object or undefined.
PASS new (class extends null { constructor() { super() } }) threw exception TypeError: super is not a constructor. PASS new (class extends null { constructor() { super() } }) threw exception TypeError: Super constructor null of anonymous class is not a constructor.
PASS new (class { constructor() { super() } }) threw exception SyntaxError: 'super' keyword unexpected here. PASS new (class { constructor() { super() } }) threw exception SyntaxError: 'super' keyword unexpected here.
PASS function x() { super(); } threw exception SyntaxError: 'super' keyword unexpected here. PASS function x() { super(); } threw exception SyntaxError: 'super' keyword unexpected here.
PASS new (class extends Object { constructor() { function x() { super() } } }) threw exception SyntaxError: 'super' keyword unexpected here. PASS new (class extends Object { constructor() { function x() { super() } } }) threw exception SyntaxError: 'super' keyword unexpected here.
......
...@@ -78,12 +78,12 @@ shouldBeFalse('x instanceof Base'); ...@@ -78,12 +78,12 @@ shouldBeFalse('x instanceof Base');
shouldThrow('new (class extends Base { constructor() { } })', '"ReferenceError: this is not defined"'); shouldThrow('new (class extends Base { constructor() { } })', '"ReferenceError: this is not defined"');
shouldThrow('new (class extends Base { constructor() { return 1; } })', '"TypeError: Derived constructors may only return object or undefined"'); shouldThrow('new (class extends Base { constructor() { return 1; } })', '"TypeError: Derived constructors may only return object or undefined"');
shouldThrow('new (class extends null { constructor() { return undefined } })'); shouldThrow('new (class extends null { constructor() { return undefined } })');
shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '"TypeError: super is not a constructor"'); shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '"TypeError: Super constructor null of anonymous class is not a constructor"');
shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x'); shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x');
shouldBeTrue('x instanceof Object'); shouldBeTrue('x instanceof Object');
shouldThrow('new (class extends null { constructor() { } })', '"ReferenceError: this is not defined"'); shouldThrow('new (class extends null { constructor() { } })', '"ReferenceError: this is not defined"');
shouldThrow('new (class extends null { constructor() { return 1; } })', '"TypeError: Derived constructors may only return object or undefined"'); shouldThrow('new (class extends null { constructor() { return 1; } })', '"TypeError: Derived constructors may only return object or undefined"');
shouldThrow('new (class extends null { constructor() { super() } })', '"TypeError: super is not a constructor"'); shouldThrow('new (class extends null { constructor() { super() } })', '"TypeError: Super constructor null of anonymous class is not a constructor"');
shouldThrow('new (class { constructor() { super() } })', '"SyntaxError: \'super\' keyword unexpected here"'); shouldThrow('new (class { constructor() { super() } })', '"SyntaxError: \'super\' keyword unexpected here"');
shouldThrow('function x() { super(); }', '"SyntaxError: \'super\' keyword unexpected here"'); shouldThrow('function x() { super(); }', '"SyntaxError: \'super\' keyword unexpected here"');
shouldThrow('new (class extends Object { constructor() { function x() { super() } } })', '"SyntaxError: \'super\' keyword unexpected here"'); shouldThrow('new (class extends Object { constructor() { function x() { super() } } })', '"SyntaxError: \'super\' keyword unexpected here"');
......
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