[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}
This commit is contained in:
rmcilroy 2016-09-06 04:53:05 -07:00 committed by Commit bot
parent 1001ddf20f
commit c950256013
4 changed files with 47 additions and 56 deletions

View File

@ -1151,13 +1151,13 @@ Node* BytecodeGraphBuilder::ProcessCallNewArguments(
const Operator* call_new_op, Node* callee, Node* new_target,
interpreter::Register first_arg, size_t arity) {
Node** all = local_zone()->NewArray<Node*>(arity);
all[0] = new_target;
all[0] = callee;
int first_arg_index = first_arg.index();
for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
all[i] = environment()->LookupRegister(
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);
return value;
}

View File

@ -1469,7 +1469,12 @@ void Interpreter::DoTailCall(InterpreterAssembler* assembler) {
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* first_arg_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(first_arg_reg);
@ -1480,15 +1485,6 @@ void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) {
__ 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>
//
// Implements the semantic equivalent of calling the runtime function
@ -1506,7 +1502,13 @@ void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
__ 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.
Node* function_id = __ BytecodeOperandRuntimeId(0);
Node* first_arg_reg = __ BytecodeOperandReg(1);
@ -1526,17 +1528,11 @@ void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) {
__ 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
// 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) {
DoCallRuntimeForPairCommon(assembler);
}
void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) {
// Call the JS runtime function that has the |context_index| with the receiver
// in register |receiver| and |arg_count| arguments in subsequent registers.
void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) {
Node* context_index = __ BytecodeOperandIdx(0);
Node* receiver_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(receiver_reg);
@ -1557,15 +1553,13 @@ void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) {
__ 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
// in register |receiver| and |arg_count| arguments in subsequent registers.
void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) {
DoCallJSRuntimeCommon(assembler);
}
void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
// 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) {
Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
Node* new_target = __ GetAccumulator();
Node* constructor_reg = __ BytecodeOperandReg(0);
@ -1582,16 +1576,6 @@ void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
__ 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>
//
// Test if the value in the <src> register equals the accumulator.

View File

@ -124,18 +124,6 @@ class Interpreter {
// Generates code to perform a JS call that collects type feedback.
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.
void DoDelete(Runtime::FunctionId function_id,
InterpreterAssembler* assembler);
@ -148,9 +136,6 @@ class Interpreter {
void DoStaLookupSlot(LanguageMode language_mode,
InterpreterAssembler* assembler);
// Generates a node with the undefined constant.
compiler::Node* BuildLoadUndefined(InterpreterAssembler* assembler);
// Generates code to load a context slot.
compiler::Node* BuildLoadContextSlot(InterpreterAssembler* assembler);

View File

@ -0,0 +1,22 @@
// 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();