Commit c9502560 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Turbofan] Fix CallSuper argument order in BytecodeGraphBuilder.

The constructor and new.target arguments were passed to CallConstruct in
the wrong order by BytecodeGraphBuilder, which caused subclassing to be
incorrect when optimizing from bytecode.

Also clean up some unecessary functions in interpreter.cc found while
figuring this out.

BUG=chromium:642409

Review-Url: https://codereview.chromium.org/2312103002
Cr-Commit-Position: refs/heads/master@{#39204}
parent 1001ddf2
...@@ -1151,13 +1151,13 @@ Node* BytecodeGraphBuilder::ProcessCallNewArguments( ...@@ -1151,13 +1151,13 @@ Node* BytecodeGraphBuilder::ProcessCallNewArguments(
const Operator* call_new_op, Node* callee, Node* new_target, const Operator* call_new_op, Node* callee, Node* new_target,
interpreter::Register first_arg, size_t arity) { interpreter::Register first_arg, size_t arity) {
Node** all = local_zone()->NewArray<Node*>(arity); Node** all = local_zone()->NewArray<Node*>(arity);
all[0] = new_target; all[0] = callee;
int first_arg_index = first_arg.index(); int first_arg_index = first_arg.index();
for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
all[i] = environment()->LookupRegister( all[i] = environment()->LookupRegister(
interpreter::Register(first_arg_index + i - 1)); interpreter::Register(first_arg_index + i - 1));
} }
all[arity - 1] = callee; all[arity - 1] = new_target;
Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false); Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
return value; return value;
} }
......
...@@ -1469,7 +1469,12 @@ void Interpreter::DoTailCall(InterpreterAssembler* assembler) { ...@@ -1469,7 +1469,12 @@ void Interpreter::DoTailCall(InterpreterAssembler* assembler) {
DoJSCall(assembler, TailCallMode::kAllow); DoJSCall(assembler, TailCallMode::kAllow);
} }
void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) { // CallRuntime <function_id> <first_arg> <arg_count>
//
// Call the runtime function |function_id| with the first argument in
// register |first_arg| and |arg_count| arguments in subsequent
// registers.
void Interpreter::DoCallRuntime(InterpreterAssembler* assembler) {
Node* function_id = __ BytecodeOperandRuntimeId(0); Node* function_id = __ BytecodeOperandRuntimeId(0);
Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(first_arg_reg); Node* first_arg = __ RegisterLocation(first_arg_reg);
...@@ -1480,15 +1485,6 @@ void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) { ...@@ -1480,15 +1485,6 @@ void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) {
__ Dispatch(); __ Dispatch();
} }
// CallRuntime <function_id> <first_arg> <arg_count>
//
// Call the runtime function |function_id| with the first argument in
// register |first_arg| and |arg_count| arguments in subsequent
// registers.
void Interpreter::DoCallRuntime(InterpreterAssembler* assembler) {
DoCallRuntimeCommon(assembler);
}
// InvokeIntrinsic <function_id> <first_arg> <arg_count> // InvokeIntrinsic <function_id> <first_arg> <arg_count>
// //
// Implements the semantic equivalent of calling the runtime function // Implements the semantic equivalent of calling the runtime function
...@@ -1506,7 +1502,13 @@ void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) { ...@@ -1506,7 +1502,13 @@ void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
__ Dispatch(); __ Dispatch();
} }
void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) { // CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
//
// Call the runtime function |function_id| which returns a pair, with the
// first argument in register |first_arg| and |arg_count| arguments in
// subsequent registers. Returns the result in <first_return> and
// <first_return + 1>
void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) {
// Call the runtime function. // Call the runtime function.
Node* function_id = __ BytecodeOperandRuntimeId(0); Node* function_id = __ BytecodeOperandRuntimeId(0);
Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg_reg = __ BytecodeOperandReg(1);
...@@ -1526,17 +1528,11 @@ void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) { ...@@ -1526,17 +1528,11 @@ void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) {
__ Dispatch(); __ Dispatch();
} }
// CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return> // CallJSRuntime <context_index> <receiver> <arg_count>
// //
// Call the runtime function |function_id| which returns a pair, with the // Call the JS runtime function that has the |context_index| with the receiver
// first argument in register |first_arg| and |arg_count| arguments in // in register |receiver| and |arg_count| arguments in subsequent registers.
// subsequent registers. Returns the result in <first_return> and void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) {
// <first_return + 1>
void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) {
DoCallRuntimeForPairCommon(assembler);
}
void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) {
Node* context_index = __ BytecodeOperandIdx(0); Node* context_index = __ BytecodeOperandIdx(0);
Node* receiver_reg = __ BytecodeOperandReg(1); Node* receiver_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(receiver_reg); Node* first_arg = __ RegisterLocation(receiver_reg);
...@@ -1557,15 +1553,13 @@ void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) { ...@@ -1557,15 +1553,13 @@ void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) {
__ Dispatch(); __ Dispatch();
} }
// CallJSRuntime <context_index> <receiver> <arg_count> // New <constructor> <first_arg> <arg_count>
// //
// Call the JS runtime function that has the |context_index| with the receiver // Call operator new with |constructor| and the first argument in
// in register |receiver| and |arg_count| arguments in subsequent registers. // register |first_arg| and |arg_count| arguments in subsequent
void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) { // registers. The new.target is in the accumulator.
DoCallJSRuntimeCommon(assembler); //
} void Interpreter::DoNew(InterpreterAssembler* assembler) {
void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_); Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
Node* new_target = __ GetAccumulator(); Node* new_target = __ GetAccumulator();
Node* constructor_reg = __ BytecodeOperandReg(0); Node* constructor_reg = __ BytecodeOperandReg(0);
...@@ -1582,16 +1576,6 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) { ...@@ -1582,16 +1576,6 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
__ Dispatch(); __ Dispatch();
} }
// New <constructor> <first_arg> <arg_count>
//
// Call operator new with |constructor| and the first argument in
// register |first_arg| and |arg_count| arguments in subsequent
// registers. The new.target is in the accumulator.
//
void Interpreter::DoNew(InterpreterAssembler* assembler) {
DoCallConstruct(assembler);
}
// TestEqual <src> // TestEqual <src>
// //
// Test if the value in the <src> register equals the accumulator. // Test if the value in the <src> register equals the accumulator.
......
...@@ -124,18 +124,6 @@ class Interpreter { ...@@ -124,18 +124,6 @@ class Interpreter {
// Generates code to perform a JS call that collects type feedback. // Generates code to perform a JS call that collects type feedback.
void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode); void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode);
// Generates code to perform a runtime call.
void DoCallRuntimeCommon(InterpreterAssembler* assembler);
// Generates code to perform a runtime call returning a pair.
void DoCallRuntimeForPairCommon(InterpreterAssembler* assembler);
// Generates code to perform a JS runtime call.
void DoCallJSRuntimeCommon(InterpreterAssembler* assembler);
// Generates code to perform a constructor call.
void DoCallConstruct(InterpreterAssembler* assembler);
// Generates code to perform delete via function_id. // Generates code to perform delete via function_id.
void DoDelete(Runtime::FunctionId function_id, void DoDelete(Runtime::FunctionId function_id,
InterpreterAssembler* assembler); InterpreterAssembler* assembler);
...@@ -148,9 +136,6 @@ class Interpreter { ...@@ -148,9 +136,6 @@ class Interpreter {
void DoStaLookupSlot(LanguageMode language_mode, void DoStaLookupSlot(LanguageMode language_mode,
InterpreterAssembler* assembler); InterpreterAssembler* assembler);
// Generates a node with the undefined constant.
compiler::Node* BuildLoadUndefined(InterpreterAssembler* assembler);
// Generates code to load a context slot. // Generates code to load a context slot.
compiler::Node* BuildLoadContextSlot(InterpreterAssembler* assembler); compiler::Node* BuildLoadContextSlot(InterpreterAssembler* assembler);
......
// Copyright 2016 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
class SuperClass {
}
class SubClass extends SuperClass {
constructor() {
super();
this.doSomething();
}
doSomething() {
}
}
new SubClass();
new SubClass();
%OptimizeFunctionOnNextCall(SubClass);
new SubClass();
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