[turbofan] Support handling of default super calls.
authormstarzinger <mstarzinger@chromium.org>
Mon, 20 Jul 2015 13:50:19 +0000 (06:50 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 20 Jul 2015 13:50:26 +0000 (13:50 +0000)
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
src/compiler/ast-graph-builder.cc
src/compiler/linkage.cc
src/runtime/runtime-classes.cc

index c729d81..db05e3e 100644 (file)
@@ -1935,22 +1935,21 @@ void Genesis::InitializeGlobal_harmony_unicode_regexps() {
 
 void Genesis::InitializeGlobal_harmony_reflect() {
   Handle<JSObject> builtins(native_context()->builtins());
-  // Install references to functions of the Reflect object
-  if (FLAG_harmony_reflect || FLAG_harmony_spreadcalls) {
-    Handle<JSFunction> apply = InstallFunction(
-        builtins, "$reflectApply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
-        MaybeHandle<JSObject>(), Builtins::kReflectApply);
-    Handle<JSFunction> construct = InstallFunction(
-        builtins, "$reflectConstruct", JS_OBJECT_TYPE, JSObject::kHeaderSize,
-        MaybeHandle<JSObject>(), 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<JSFunction> apply = InstallFunction(
+      builtins, "$reflectApply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+      MaybeHandle<JSObject>(), Builtins::kReflectApply);
+  apply->shared()->set_internal_formal_parameter_count(3);
+  apply->shared()->set_length(3);
+
+  Handle<JSFunction> construct = InstallFunction(
+      builtins, "$reflectConstruct", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+      MaybeHandle<JSObject>(), Builtins::kReflectConstruct);
+  construct->shared()->set_internal_formal_parameter_count(3);
+  construct->shared()->set_length(2);
 
   if (!FLAG_harmony_reflect) return;
+
   Handle<JSGlobalObject> global(JSGlobalObject::cast(
       native_context()->global_object()));
   Handle<String> reflect_string =
index 9a28391..6f9371a 100644 (file)
@@ -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();
   }
index 0c43c2d..691a3b3 100644 (file)
@@ -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:
index 7b42c1d..92df7fe 100644 (file)
@@ -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<Object> 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<FixedArray> elements =
+      isolate->factory()->NewUninitializedFixedArray(argument_count);
+  for (int i = 0; i < argument_count; ++i) {
+    elements->set(i, frame->GetParameter(i));
+  }
+  Handle<JSArray> arguments = isolate->factory()->NewJSArrayWithElements(
+      elements, FAST_ELEMENTS, argument_count);
+
+  // Call $reflectConstruct(<super>, <args>, <new.target>) now.
+  Handle<Object> 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<Object> argv[] = {super_constructor, arguments, original_constructor};
+  Handle<Object> 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