From 37c2094e8c956e4ef816e7de1a2da9db78e5623d Mon Sep 17 00:00:00 2001 From: mstarzinger Date: Mon, 20 Jul 2015 06:50:19 -0700 Subject: [PATCH] [turbofan] Support handling of default super calls. This implements the missing %DefaultConstructorCallSuper runtime functionality, thereby allowing all compilers to fall-back to that implementation when the appropriate intrinsic is missing. R=rossberg@chromium.org Review URL: https://codereview.chromium.org/1240993002 Cr-Commit-Position: refs/heads/master@{#29753} --- src/bootstrapper.cc | 25 +++++++++++----------- src/compiler/ast-graph-builder.cc | 3 +-- src/compiler/linkage.cc | 1 + src/runtime/runtime-classes.cc | 45 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index c729d81..db05e3e8 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1935,22 +1935,21 @@ void Genesis::InitializeGlobal_harmony_unicode_regexps() { void Genesis::InitializeGlobal_harmony_reflect() { Handle builtins(native_context()->builtins()); - // Install references to functions of the Reflect object - if (FLAG_harmony_reflect || FLAG_harmony_spreadcalls) { - Handle apply = InstallFunction( - builtins, "$reflectApply", JS_OBJECT_TYPE, JSObject::kHeaderSize, - MaybeHandle(), Builtins::kReflectApply); - Handle construct = InstallFunction( - builtins, "$reflectConstruct", JS_OBJECT_TYPE, JSObject::kHeaderSize, - MaybeHandle(), Builtins::kReflectConstruct); - apply->shared()->set_internal_formal_parameter_count(3); - apply->shared()->set_length(3); - construct->shared()->set_internal_formal_parameter_count(3); - construct->shared()->set_length(2); - } + Handle apply = InstallFunction( + builtins, "$reflectApply", JS_OBJECT_TYPE, JSObject::kHeaderSize, + MaybeHandle(), Builtins::kReflectApply); + apply->shared()->set_internal_formal_parameter_count(3); + apply->shared()->set_length(3); + + Handle construct = InstallFunction( + builtins, "$reflectConstruct", JS_OBJECT_TYPE, JSObject::kHeaderSize, + MaybeHandle(), Builtins::kReflectConstruct); + construct->shared()->set_internal_formal_parameter_count(3); + construct->shared()->set_length(2); if (!FLAG_harmony_reflect) return; + Handle global(JSGlobalObject::cast( native_context()->global_object())); Handle reflect_string = diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 9a28391..6f9371a 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -2583,8 +2583,7 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { // TODO(mstarzinger): This bailout is a gigantic hack, the owner is ashamed. if (function->function_id == Runtime::kInlineGeneratorNext || - function->function_id == Runtime::kInlineGeneratorThrow || - function->function_id == Runtime::kInlineDefaultConstructorCallSuper) { + function->function_id == Runtime::kInlineGeneratorThrow) { ast_context()->ProduceValue(jsgraph()->TheHoleConstant()); return SetStackOverflow(); } diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc index 0c43c2d..691a3b3 100644 --- a/src/compiler/linkage.cc +++ b/src/compiler/linkage.cc @@ -194,6 +194,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) { return 0; case Runtime::kInlineArguments: case Runtime::kInlineCallFunction: + case Runtime::kInlineDefaultConstructorCallSuper: case Runtime::kInlineGetCallerJSFunction: case Runtime::kInlineGetPrototype: case Runtime::kInlineRegExpExec: diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc index 7b42c1d..92df7fe 100644 --- a/src/runtime/runtime-classes.cc +++ b/src/runtime/runtime-classes.cc @@ -521,8 +521,49 @@ RUNTIME_FUNCTION(Runtime_HandleStepInForDerivedConstructors) { RUNTIME_FUNCTION(Runtime_DefaultConstructorCallSuper) { - UNIMPLEMENTED(); - return nullptr; + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, original_constructor, 0); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, actual_constructor, 1); + JavaScriptFrameIterator it(isolate); + + // Prepare the callee to the super call. The super constructor is stored as + // the prototype of the constructor we are currently executing. + Handle super_constructor; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, super_constructor, + Runtime::GetPrototype(isolate, actual_constructor)); + + // Find the frame that holds the actual arguments passed to the function. + it.AdvanceToArgumentsFrame(); + JavaScriptFrame* frame = it.frame(); + + // Prepare the array containing all passed arguments. + int argument_count = frame->GetArgumentsLength(); + Handle elements = + isolate->factory()->NewUninitializedFixedArray(argument_count); + for (int i = 0; i < argument_count; ++i) { + elements->set(i, frame->GetParameter(i)); + } + Handle arguments = isolate->factory()->NewJSArrayWithElements( + elements, FAST_ELEMENTS, argument_count); + + // Call $reflectConstruct(, , ) now. + Handle reflect; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, reflect, + Object::GetProperty(isolate, + handle(isolate->native_context()->builtins()), + "$reflectConstruct")); + RUNTIME_ASSERT(reflect->IsJSFunction()); // Depends on --harmony-reflect. + Handle argv[] = {super_constructor, arguments, original_constructor}; + Handle result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, result, + Execution::Call(isolate, reflect, isolate->factory()->undefined_value(), + arraysize(argv), argv)); + + return *result; } } // namespace internal } // namespace v8 -- 2.7.4