Install ConstructNonConstructable as construct stub for non-constructables.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#32223}
This commit is contained in:
verwaest 2015-11-24 09:16:40 -08:00 committed by Commit bot
parent 515093630a
commit 8e28e851ee
38 changed files with 229 additions and 135 deletions

View File

@ -445,7 +445,9 @@ Handle<JSFunction> ApiNatives::CreateApiFunction(
} else {
code = isolate->builtins()->HandleApiCall();
}
Handle<Code> construct_stub = isolate->builtins()->JSConstructStubApi();
Handle<Code> construct_stub =
prototype.is_null() ? isolate->builtins()->ConstructedNonConstructable()
: isolate->builtins()->JSConstructStubApi();
obj->set_instantiated(true);
Handle<JSFunction> result;

View File

@ -647,6 +647,13 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
}
void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ push(r1);
__ CallRuntime(Runtime::kThrowConstructedNonConstructable, 1);
}
enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
@ -1685,7 +1692,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0);
__ push(r1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1);
}
}
@ -1813,11 +1821,8 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
// Called Construct on an Object that doesn't have a [[Construct]] internal
// method.
__ bind(&non_constructor);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r1);
__ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
__ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
RelocInfo::CODE_TARGET);
}

View File

@ -654,6 +654,13 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
}
void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(x1);
__ CallRuntime(Runtime::kThrowConstructedNonConstructable, 1);
}
enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
@ -1673,7 +1680,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0);
__ Push(x1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1);
}
}
@ -1800,11 +1808,8 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
// Called Construct on an Object that doesn't have a [[Construct]] internal
// method.
__ bind(&non_constructor);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(x1);
__ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
__ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
RelocInfo::CODE_TARGET);
}

View File

@ -395,7 +395,7 @@ Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<Name> name,
Isolate* isolate = target->GetIsolate();
Factory* factory = isolate->factory();
Handle<String> name_string = Name::ToFunctionName(name).ToHandleChecked();
Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call));
Handle<Code> call_code(isolate->builtins()->builtin(call));
Handle<JSObject> prototype;
static const bool kReadOnlyPrototype = false;
static const bool kInstallConstructor = false;
@ -557,7 +557,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
}
// Allocate the empty function as the prototype for function - ES6 19.2.3
Handle<Code> code(isolate->builtins()->builtin(Builtins::kEmptyFunction));
Handle<Code> code(isolate->builtins()->EmptyFunction());
Handle<JSFunction> empty_function =
factory->NewFunctionWithoutPrototype(factory->empty_string(), code);
@ -973,8 +973,7 @@ Handle<JSGlobalObject> Genesis::CreateNewGlobals(
if (js_global_object_template.is_null()) {
Handle<String> name = Handle<String>(heap()->empty_string());
Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin(
Builtins::kIllegal));
Handle<Code> code = isolate()->builtins()->Illegal();
Handle<JSObject> prototype =
factory()->NewFunctionPrototype(isolate()->object_function());
js_global_object_function = factory()->NewFunction(
@ -1004,8 +1003,7 @@ Handle<JSGlobalObject> Genesis::CreateNewGlobals(
Handle<JSFunction> global_proxy_function;
if (global_proxy_template.IsEmpty()) {
Handle<String> name = Handle<String>(heap()->empty_string());
Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin(
Builtins::kIllegal));
Handle<Code> code = isolate()->builtins()->Illegal();
global_proxy_function = factory()->NewFunction(
name, code, JS_GLOBAL_PROXY_TYPE, JSGlobalProxy::kSize);
} else {
@ -1103,7 +1101,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
function_function->initial_map()->set_is_callable();
function_function->initial_map()->set_is_constructor(true);
function_function->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
{ // --- A r r a y ---
Handle<JSFunction> array_function =
@ -1161,7 +1159,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kIllegal);
native_context()->set_number_function(*number_fun);
number_fun->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
}
{ // --- B o o l e a n ---
@ -1176,8 +1174,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<JSFunction> string_fun = InstallFunction(
global, "String", JS_VALUE_TYPE, JSValue::kSize,
isolate->initial_object_prototype(), Builtins::kStringConstructor);
string_fun->shared()->set_construct_stub(isolate->builtins()->builtin(
Builtins::kStringConstructor_ConstructStub));
string_fun->shared()->set_construct_stub(
*isolate->builtins()->StringConstructor_ConstructStub());
string_fun->shared()->DontAdaptArguments();
string_fun->shared()->set_length(1);
native_context()->set_string_function(*string_fun);
@ -1203,8 +1201,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<JSFunction> symbol_fun = InstallFunction(
global, "Symbol", JS_VALUE_TYPE, JSValue::kSize,
isolate->initial_object_prototype(), Builtins::kSymbolConstructor);
symbol_fun->shared()->set_construct_stub(isolate->builtins()->builtin(
Builtins::kSymbolConstructor_ConstructStub));
symbol_fun->shared()->set_construct_stub(
*isolate->builtins()->SymbolConstructor_ConstructStub());
symbol_fun->shared()->set_internal_formal_parameter_count(1);
symbol_fun->shared()->set_length(1);
native_context()->set_symbol_function(*symbol_fun);
@ -1216,7 +1214,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
global, "Date", JS_DATE_TYPE, JSDate::kSize,
isolate->initial_object_prototype(), Builtins::kIllegal);
date_fun->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
}
{ // -- R e g E x p
@ -1227,7 +1225,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kIllegal);
native_context()->set_regexp_function(*regexp_fun);
regexp_fun->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
DCHECK(regexp_fun->has_initial_map());
Handle<Map> initial_map(regexp_fun->initial_map());
@ -1308,7 +1306,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kIllegal);
native_context()->set_data_view_fun(*data_view_fun);
data_view_fun->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
}
{ // -- M a p
@ -1359,7 +1357,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
// This is done by introducing an anonymous function with
// class_name equals 'Arguments'.
Handle<String> arguments_string = factory->Arguments_string();
Handle<Code> code(isolate->builtins()->builtin(Builtins::kIllegal));
Handle<Code> code = isolate->builtins()->Illegal();
Handle<JSFunction> function = factory->NewFunctionWithoutPrototype(
arguments_string, code);
function->shared()->set_instance_class_name(*arguments_string);
@ -1464,8 +1462,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{ // --- context extension
// Create a function for the context extension objects.
Handle<Code> code = Handle<Code>(
isolate->builtins()->builtin(Builtins::kIllegal));
Handle<Code> code = isolate->builtins()->Illegal();
Handle<JSFunction> context_extension_fun = factory->NewFunction(
factory->empty_string(), code, JS_CONTEXT_EXTENSION_OBJECT_TYPE,
JSObject::kHeaderSize);
@ -1479,9 +1476,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{
// Set up the call-as-function delegate.
Handle<Code> code =
Handle<Code>(isolate->builtins()->builtin(
Builtins::kHandleApiCallAsFunction));
Handle<Code> code = isolate->builtins()->HandleApiCallAsFunction();
Handle<JSFunction> delegate = factory->NewFunction(
factory->empty_string(), code, JS_OBJECT_TYPE, JSObject::kHeaderSize);
native_context()->set_call_as_function_delegate(*delegate);
@ -1490,9 +1485,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{
// Set up the call-as-constructor delegate.
Handle<Code> code =
Handle<Code>(isolate->builtins()->builtin(
Builtins::kHandleApiCallAsConstructor));
Handle<Code> code = isolate->builtins()->HandleApiCallAsConstructor();
Handle<JSFunction> delegate = factory->NewFunction(
factory->empty_string(), code, JS_OBJECT_TYPE, JSObject::kHeaderSize);
native_context()->set_call_as_constructor_delegate(*delegate);
@ -1835,7 +1828,7 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
generator_function_function->initial_map()->set_is_callable();
generator_function_function->initial_map()->set_is_constructor(true);
generator_function_function->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
}
{ // -- S e t I t e r a t o r
@ -2194,7 +2187,7 @@ void Genesis::InitializeGlobal_harmony_proxies() {
// TODO(verwaest): Set to null in InstallFunction.
proxy_fun->initial_map()->set_prototype(isolate->heap()->null_value());
proxy_fun->shared()->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate->builtins()->JSBuiltinsConstructStub());
native_context()->set_proxy_function(*proxy_fun);
}
@ -2450,7 +2443,7 @@ bool Genesis::InstallNatives(ContextType context_type) {
JSFunction::EnsureHasInitialMap(function);
function->initial_map()->set_instance_type(JS_PROMISE_TYPE);
function->shared()->set_construct_stub(
isolate()->builtins()->builtin(Builtins::kJSBuiltinsConstructStub));
*isolate()->builtins()->JSBuiltinsConstructStub());
}
InstallBuiltinFunctionIds();

View File

@ -86,6 +86,8 @@ enum BuiltinExtraArguments {
#define BUILTIN_LIST_A(V) \
V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
V(ConstructedNonConstructable, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
V(CallFunction_ReceiverIsNullOrUndefined, BUILTIN, UNINITIALIZED, \
kNoExtraICState) \
V(CallFunction_ReceiverIsNotNullOrUndefined, BUILTIN, UNINITIALIZED, \
@ -283,6 +285,7 @@ class Builtins {
static void Generate_Adaptor(MacroAssembler* masm,
CFunctionId id,
BuiltinExtraArguments extra_args);
static void Generate_ConstructedNonConstructable(MacroAssembler* masm);
static void Generate_CompileLazy(MacroAssembler* masm);
static void Generate_InOptimizationQueue(MacroAssembler* masm);
static void Generate_CompileOptimized(MacroAssembler* masm);

View File

@ -746,7 +746,7 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
Handle<SharedFunctionInfo> shared = info->shared_info();
FunctionLiteral* lit = info->literal();
shared->set_language_mode(lit->language_mode());
DCHECK_EQ(shared->language_mode(), lit->language_mode());
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
MaybeDisableOptimization(shared, lit->dont_optimize_reason());

View File

@ -216,10 +216,10 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
// Raise a TypeError if the {target} is a "classConstructor".
if (IsClassConstructor(shared->kind())) {
NodeProperties::RemoveFrameStateInput(node, 0);
NodeProperties::RemoveValueInputs(node);
NodeProperties::ReplaceValueInputs(node, target);
NodeProperties::ChangeOp(
node, javascript()->CallRuntime(
Runtime::kThrowConstructorNonCallableError, 0));
Runtime::kThrowConstructorNonCallableError, 1));
return Changed(node);
}

View File

@ -291,6 +291,15 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
return NoChange();
}
if (node->opcode() == IrOpcode::kJSCallConstruct &&
!function->IsConstructor()) {
// Constructor must be constructable.
TRACE("Not inlining %s into %s since constructor is not constructable.\n",
function->shared()->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
return NoChange();
}
// Class constructors are callable, but [[Call]] will raise an exception.
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
if (IsClassConstructor(function->shared()->kind())) {
@ -418,6 +427,8 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// constructor dispatch and turn the constructor call into a regular call.
// This models the behavior usually accomplished by our {JSConstructStub}.
// Note that the context has to be the callers context (input to call node).
// TODO(4544): Once we support inlining builtins, make sure no implicit
// receiver is created for builtins that don't expect any.
if (node->opcode() == IrOpcode::kJSCallConstruct) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* context = NodeProperties::GetContextInput(node);

View File

@ -1398,8 +1398,7 @@ Reduction JSTypedLowering::ReduceJSCreate(Node* node) {
target_type->AsConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> constructor =
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
// Check that function is a constructor.
if (!constructor->IsConstructor()) return NoChange();
DCHECK(constructor->IsConstructor());
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
if (constructor->IsInobjectSlackTrackingInProgress()) {

View File

@ -1146,9 +1146,6 @@ void LiveEdit::ReplaceFunctionCode(
LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
shared_info->set_construct_stub(
isolate->builtins()->builtin(Builtins::kJSConstructStubGeneric));
DeoptimizeDependentFunctions(*shared_info);
isolate->compilation_cache()->Remove(shared_info);
}

View File

@ -1202,7 +1202,8 @@ Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
Handle<String> name,
MaybeHandle<Code> code) {
Handle<Context> context(isolate()->native_context());
Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name, code);
Handle<SharedFunctionInfo> info =
NewSharedFunctionInfo(name, code, map->is_constructor());
DCHECK(is_sloppy(info->language_mode()) &&
(map.is_identical_to(isolate()->sloppy_function_map()) ||
map.is_identical_to(
@ -2022,7 +2023,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<TypeFeedbackVector> feedback_vector) {
DCHECK(IsValidFunctionKind(kind));
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(
name, code, IsConstructable(kind, scope_info->language_mode()));
shared->set_scope_info(*scope_info);
shared->set_feedback_vector(*feedback_vector);
shared->set_kind(kind);
@ -2055,8 +2057,7 @@ Handle<JSMessageObject> Factory::NewJSMessageObject(
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name,
MaybeHandle<Code> maybe_code) {
Handle<String> name, MaybeHandle<Code> maybe_code, bool is_constructor) {
Handle<Map> map = shared_function_info_map();
Handle<SharedFunctionInfo> share = New<SharedFunctionInfo>(map, OLD_SPACE);
@ -2064,14 +2065,15 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
share->set_name(*name);
Handle<Code> code;
if (!maybe_code.ToHandle(&code)) {
code = handle(isolate()->builtins()->builtin(Builtins::kIllegal));
code = isolate()->builtins()->Illegal();
}
share->set_code(*code);
share->set_optimized_code_map(*cleared_optimized_code_map());
share->set_scope_info(ScopeInfo::Empty(isolate()));
Code* construct_stub =
isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
share->set_construct_stub(construct_stub);
Handle<Code> construct_stub =
is_constructor ? isolate()->builtins()->JSConstructStubGeneric()
: isolate()->builtins()->ConstructedNonConstructable();
share->set_construct_stub(*construct_stub);
share->set_instance_class_name(*Object_string());
share->set_function_data(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);

View File

@ -627,7 +627,8 @@ class Factory final {
Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<TypeFeedbackVector> feedback_vector);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
MaybeHandle<Code> code);
MaybeHandle<Code> code,
bool is_constructor);
// Allocates a new JSMessageObject object.
Handle<JSMessageObject> NewJSMessageObject(MessageTemplate::Template message,

View File

@ -1022,6 +1022,15 @@ inline bool IsClassConstructor(FunctionKind kind) {
}
inline bool IsConstructable(FunctionKind kind, LanguageMode mode) {
if (IsAccessorFunction(kind)) return false;
if (IsConciseMethod(kind) && !IsGeneratorFunction(kind)) return false;
if (IsArrowFunction(kind)) return false;
if (is_strong(mode)) return IsClassConstructor(kind);
return true;
}
inline bool IsInObjectLiteral(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind));
return kind & FunctionKind::kInObjectLiteral;

View File

@ -410,6 +410,13 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
}
void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ push(edi);
__ CallRuntime(Runtime::kThrowConstructedNonConstructable, 1);
}
enum IsTagged { kEaxIsSmiTagged, kEaxIsUntaggedInt };
@ -1543,7 +1550,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0);
__ push(edi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1);
}
}
@ -1670,11 +1678,8 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
// Called Construct on an Object that doesn't have a [[Construct]] internal
// method.
__ bind(&non_constructor);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(edi);
__ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
__ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
RelocInfo::CODE_TARGET);
}

View File

@ -100,7 +100,7 @@ class CallSite {
T(CircularStructure, "Converting circular structure to JSON") \
T(ConstAssign, "Assignment to constant variable.") \
T(ConstructorNonCallable, \
"Class constructors cannot be invoked without 'new'") \
"Class constructor % cannot be invoked without 'new'") \
T(ConstructorNotFunction, "Constructor % requires 'new'") \
T(CurrencyCode, "Currency code is required with currency style.") \
T(DataViewNotArrayBuffer, \

View File

@ -650,6 +650,13 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
}
void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructedNonConstructable, 1);
}
enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
@ -1700,7 +1707,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1);
}
}
@ -1832,11 +1840,8 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
// Called Construct on an Object that doesn't have a [[Construct]] internal
// method.
__ bind(&non_constructor);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
__ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
RelocInfo::CODE_TARGET);
}

View File

@ -646,6 +646,13 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
}
void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructedNonConstructable, 1);
}
enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
@ -1694,7 +1701,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0);
__ Push(a1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1);
}
}
@ -1825,11 +1833,8 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
// Called Construct on an Object that doesn't have a [[Construct]] internal
// method.
__ bind(&non_constructor);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(a1);
__ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
__ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
RelocInfo::CODE_TARGET);
}

View File

@ -12732,6 +12732,10 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
shared_info->set_dont_crankshaft(lit->flags() &
AstProperties::kDontCrankshaft);
shared_info->set_kind(lit->kind());
if (!IsConstructable(lit->kind(), lit->language_mode())) {
shared_info->set_construct_stub(
*shared_info->GetIsolate()->builtins()->ConstructedNonConstructable());
}
shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
shared_info->set_asm_function(lit->scope()->asm_function());
}

View File

@ -3337,7 +3337,8 @@ ParserBase<Traits>::ParseLeftHandSideExpression(
return this->EmptyExpression();
}
int pos;
if (scanner()->current_token() == Token::IDENTIFIER) {
if (scanner()->current_token() == Token::IDENTIFIER ||
scanner()->current_token() == Token::SUPER) {
// For call of an identifier we want to report position of
// the identifier as position of the call in the stack trace.
pos = position();
@ -3677,8 +3678,8 @@ typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseSuperExpression(bool is_new,
ExpressionClassifier* classifier,
bool* ok) {
int pos = position();
Expect(Token::SUPER, CHECK_OK);
int pos = position();
Scope* scope = scope_->ReceiverScope();
FunctionKind kind = scope->function_kind();

View File

@ -321,6 +321,13 @@ void CallPrinter::VisitCallNew(CallNew* node) {
void CallPrinter::VisitCallRuntime(CallRuntime* node) {
if (node->function() ==
Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper)) {
found_ = true;
Print("super");
done_ = true;
return;
}
FindArguments(node->arguments());
}
@ -380,7 +387,9 @@ void CallPrinter::VisitThisFunction(ThisFunction* node) {}
void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {}
void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {
Print("super");
}
void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {

View File

@ -36,9 +36,11 @@ RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
HandleScope scope(isolate);
DCHECK(args.length() == 0);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
Handle<Object> name(constructor->shared()->name(), isolate);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kConstructorNonCallable));
isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name));
}

View File

@ -107,6 +107,8 @@ RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
CONVERT_ARG_CHECKED(JSFunction, f, 0);
RUNTIME_ASSERT(f->RemovePrototype());
f->shared()->set_construct_stub(
*isolate->builtins()->ConstructedNonConstructable());
return isolate->heap()->undefined_value();
}
@ -395,6 +397,8 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
bound_function->shared()->set_optimized_code_map(
isolate->heap()->cleared_optimized_code_map());
bound_function->shared()->set_inferred_name(isolate->heap()->empty_string());
bound_function->shared()->set_construct_stub(
*isolate->builtins()->JSBuiltinsConstructStub());
// Get all arguments of calling function (Function.prototype.bind).
int argc = 0;
base::SmartArrayPointer<Handle<Object>> arguments =

View File

@ -443,5 +443,15 @@ RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) {
isolate, NewTypeError(MessageTemplate::kCalledNonCallable, callsite));
}
RUNTIME_FUNCTION(Runtime_ThrowConstructedNonConstructable) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
Handle<String> callsite = RenderCallSite(isolate, object);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kNotConstructor, callsite));
}
} // namespace internal
} // namespace v8

View File

@ -1044,11 +1044,7 @@ RUNTIME_FUNCTION(Runtime_NewObject) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
// TODO(verwaest): Make sure |constructor| is guaranteed to be a constructor.
if (!constructor->IsConstructor()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
}
DCHECK(constructor->IsConstructor());
// If called through new, new.target can be:
// - a subclass of constructor,

View File

@ -73,24 +73,24 @@ namespace internal {
F(AtomicsFutexNumWaitersForTesting, 2, 1)
#define FOR_EACH_INTRINSIC_CLASSES(F) \
F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \
F(ThrowConstructorNonCallableError, 0, 1) \
F(ThrowArrayNotSubclassableError, 0, 1) \
F(ThrowStaticPrototypeError, 0, 1) \
F(ThrowIfStaticPrototype, 1, 1) \
F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 5, 1) \
F(FinalizeClassDefinition, 2, 1) \
F(DefineClassMethod, 3, 1) \
F(ClassGetSourceCode, 1, 1) \
F(LoadFromSuper, 4, 1) \
F(LoadKeyedFromSuper, 4, 1) \
F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1) \
F(StoreKeyedToSuper_Strict, 4, 1) \
F(StoreKeyedToSuper_Sloppy, 4, 1) \
#define FOR_EACH_INTRINSIC_CLASSES(F) \
F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \
F(ThrowConstructorNonCallableError, 1, 1) \
F(ThrowArrayNotSubclassableError, 0, 1) \
F(ThrowStaticPrototypeError, 0, 1) \
F(ThrowIfStaticPrototype, 1, 1) \
F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 5, 1) \
F(FinalizeClassDefinition, 2, 1) \
F(DefineClassMethod, 3, 1) \
F(ClassGetSourceCode, 1, 1) \
F(LoadFromSuper, 4, 1) \
F(LoadKeyedFromSuper, 4, 1) \
F(StoreToSuper_Strict, 4, 1) \
F(StoreToSuper_Sloppy, 4, 1) \
F(StoreKeyedToSuper_Strict, 4, 1) \
F(StoreKeyedToSuper_Sloppy, 4, 1) \
F(DefaultConstructorCallSuper, 2, 1)
@ -356,6 +356,7 @@ namespace internal {
F(GetTypeFeedbackVector, 1, 1) \
F(GetCallerJSFunction, 0, 1) \
F(GetCodeStubExportsObject, 0, 1) \
F(ThrowConstructedNonConstructable, 1, 1) \
F(ThrowCalledNonCallable, 1, 1)

View File

@ -401,6 +401,13 @@ void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
}
void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rdi);
__ CallRuntime(Runtime::kThrowConstructedNonConstructable, 1);
}
enum IsTagged { kRaxIsSmiTagged, kRaxIsUntaggedInt };
@ -1735,7 +1742,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0);
__ Push(rdi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1);
}
}
@ -1866,11 +1874,8 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
// Called Construct on an Object that doesn't have a [[Construct]] internal
// method.
__ bind(&non_constructor);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rdi);
__ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
__ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
RelocInfo::CODE_TARGET);
}

View File

@ -9858,15 +9858,16 @@ THREADED_TEST(ConstructorForObject) {
value = CompileRun("new obj2(28)");
CHECK(try_catch.HasCaught());
String::Utf8Value exception_value1(try_catch.Exception());
CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
CHECK_EQ(0,
strcmp("TypeError: obj2 is not a constructor", *exception_value1));
try_catch.Reset();
Local<Value> args[] = {v8_num(29)};
value = instance->CallAsConstructor(1, args);
CHECK(try_catch.HasCaught());
String::Utf8Value exception_value2(try_catch.Exception());
CHECK_EQ(0,
strcmp("TypeError: object is not a function", *exception_value2));
CHECK_EQ(
0, strcmp("TypeError: object is not a constructor", *exception_value2));
try_catch.Reset();
}

View File

@ -0,0 +1,19 @@
// Copyright 2015 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: --allow-natives-syntax
// This tests that inlining a constructor call to a function which cannot be
// used as a constructor (e.g. arrow function) still throws correctly.
var g = () => {}
function f() {
return new g();
}
assertThrows(f);
assertThrows(f);
%OptimizeFunctionOnNextCall(f);
assertThrows(f);

View File

@ -78,7 +78,7 @@ Graph* BytecodeGraphBuilderTest::GetCompletedGraph(
Handle<String> name = factory()->NewStringFromStaticChars("test");
Handle<String> script = factory()->NewStringFromStaticChars("test() {}");
Handle<SharedFunctionInfo> shared_info =
factory()->NewSharedFunctionInfo(name, MaybeHandle<Code>());
factory()->NewSharedFunctionInfo(name, MaybeHandle<Code>(), true);
shared_info->set_script(*factory()->NewScript(script));
if (!feedback_vector.is_null()) {
shared_info->set_feedback_vector(*feedback_vector.ToHandleChecked());

View File

@ -4,13 +4,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS new A did not throw exception.
PASS A() threw exception TypeError: Class constructors cannot be invoked without 'new'.
PASS A() threw exception TypeError: Class constructor A cannot be invoked without 'new'.
PASS new B did not throw exception.
PASS B() threw exception TypeError: Class constructors 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 (class { constructor() {} })() threw exception TypeError: Class constructors cannot be invoked without 'new'.
PASS new (class extends null { constructor() { super() } })() threw exception TypeError: function () {} is not a constructor.
PASS (class extends null { constructor() { super() } })() threw exception TypeError: Class constructors 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 (class extends null { constructor() { super() } })() threw exception TypeError: Class constructor cannot be invoked without 'new'.
PASS successfullyParsed is true
TEST COMPLETE

View File

@ -29,12 +29,12 @@ class A { constructor() {} };
class B extends A { constructor() { super() } };
shouldNotThrow('new A');
shouldThrow('A()', '"TypeError: Class constructors cannot be invoked without \'new\'"');
shouldThrow('A()', '"TypeError: Class constructor A cannot be invoked without \'new\'"');
shouldNotThrow('new B');
shouldThrow('B()', '"TypeError: Class constructors cannot be invoked without \'new\'"');
shouldThrow('B()', '"TypeError: Class constructor B cannot be invoked without \'new\'"');
shouldNotThrow('new (class { constructor() {} })()');
shouldThrow('(class { constructor() {} })()', '"TypeError: Class constructors cannot be invoked without \'new\'"');
shouldThrow('new (class extends null { constructor() { super() } })()', '"TypeError: function () {} is not a constructor"');
shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Class constructors 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('(class extends null { constructor() { super() } })()', '"TypeError: Class constructor cannot be invoked without \'new\'"');
var successfullyParsed = true;

View File

@ -4,11 +4,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS new A instanceof A is true
PASS A() threw exception TypeError: Class constructors cannot be invoked without 'new'.
PASS A() threw exception TypeError: Class constructor A cannot be invoked without 'new'.
PASS A.prototype.constructor instanceof Function is true
PASS A.prototype.constructor.name is "A"
PASS new B instanceof A; new B instanceof A is true
PASS B() threw exception TypeError: Class constructors cannot be invoked without 'new'.
PASS B() threw exception TypeError: Class constructor B cannot be invoked without 'new'.
PASS B.prototype.constructor.name is "B"
PASS A !== B is true
PASS A.prototype.constructor !== B.prototype.constructor is true

View File

@ -29,11 +29,11 @@ class A { };
class B extends A { };
shouldBeTrue('new A instanceof A');
shouldThrow('A()', '"TypeError: Class constructors cannot be invoked without \'new\'"');
shouldThrow('A()', '"TypeError: Class constructor A cannot be invoked without \'new\'"');
shouldBeTrue('A.prototype.constructor instanceof Function');
shouldBe('A.prototype.constructor.name', '"A"');
shouldBeTrue('new B instanceof A; new B instanceof A');
shouldThrow('B()', '"TypeError: Class constructors cannot be invoked without \'new\'"');
shouldThrow('B()', '"TypeError: Class constructor B cannot be invoked without \'new\'"');
shouldBe('B.prototype.constructor.name', '"B"');
shouldBeTrue('A !== B');
shouldBeTrue('A.prototype.constructor !== B.prototype.constructor');

View File

@ -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 function or null.
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 () { super(); } }) threw exception TypeError: function () {} is not a constructor.
PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: super is not a constructor.
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 class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true

View File

@ -100,7 +100,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 function or null"');
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 () { super(); } })', '"TypeError: function () {} is not a constructor"');
shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: super is not a constructor"');
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"');
shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');

View File

@ -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() { 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() { super(); return undefined } }) threw exception TypeError: function () {} is not a constructor.
PASS new (class extends null { constructor() { super(); return undefined } }) threw exception TypeError: super is not a constructor.
PASS x = { }; new (class extends null { constructor() { return x } }); is x
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() { return 1; } }) threw exception TypeError: Derived constructors may only return object or undefined.
PASS new (class extends null { constructor() { super() } }) threw exception TypeError: function () {} is not a constructor.
PASS new (class extends null { constructor() { super() } }) threw exception TypeError: super is not a constructor.
PASS new (class { constructor() { 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.

View File

@ -80,12 +80,12 @@ shouldBeFalse('x instanceof Base');
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 null { constructor() { return undefined } })');
shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '"TypeError: function () {} is not a constructor"');
shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '"TypeError: super is not a constructor"');
shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x');
shouldBeTrue('x instanceof Object');
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() { super() } })', '"TypeError: function () {} is not a constructor"');
shouldThrow('new (class extends null { constructor() { super() } })', '"TypeError: super is not a constructor"');
shouldThrow('new (class { constructor() { 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"');

View File

@ -26,7 +26,7 @@ Test for correct handling of exceptions from instanceof and 'new' expressions
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS new {}.undefined threw exception TypeError: (intermediate value).undefined is not a function.
PASS new {}.undefined threw exception TypeError: (intermediate value).undefined is not a constructor.
PASS 1 instanceof {}.undefined threw exception TypeError: Expecting a function in instanceof check, but got undefined.
PASS successfullyParsed is true