[turbofan] Fix usage of ThisFunction parameter in OSR.

R=mstarzinger@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#26355}
This commit is contained in:
titzer 2015-01-30 05:09:32 -08:00 committed by Commit bot
parent 32fe247d91
commit e25a0f7e4e
22 changed files with 265 additions and 39 deletions

View File

@ -35,9 +35,10 @@ struct ArmLinkageHelperTraits {
typedef LinkageHelper<ArmLinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, int parameter_count,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
return LH::GetJSCallDescriptor(zone, is_osr, parameter_count, flags);
}

View File

@ -35,9 +35,10 @@ struct Arm64LinkageHelperTraits {
typedef LinkageHelper<Arm64LinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, int parameter_count,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
return LH::GetJSCallDescriptor(zone, is_osr, parameter_count, flags);
}

View File

@ -7,6 +7,7 @@
#include "src/compiler.h"
#include "src/compiler/ast-loop-assignment-analyzer.h"
#include "src/compiler/control-builders.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h"
@ -35,8 +36,8 @@ AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
Node* AstGraphBuilder::GetFunctionClosure() {
if (!function_closure_.is_set()) {
// Parameter -1 is special for the function closure
const Operator* op = common()->Parameter(-1);
const Operator* op =
common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex);
Node* node = NewNode(op, graph()->start());
function_closure_.set(node);
}

View File

@ -315,11 +315,11 @@ const Operator* CommonOperatorBuilder::Parameter(int index) {
const Operator* CommonOperatorBuilder::OsrValue(int index) {
return new (zone()) Operator1<int>( // --
IrOpcode::kOsrValue, Operator::kPure, // opcode
"OsrValue", // name
0, 0, 1, 1, 0, 0, // counts
index); // parameter
return new (zone()) Operator1<int>( // --
IrOpcode::kOsrValue, Operator::kNoProperties, // opcode
"OsrValue", // name
0, 0, 1, 1, 0, 0, // counts
index); // parameter
}

View File

@ -30,9 +30,10 @@ struct IA32LinkageHelperTraits {
typedef LinkageHelper<IA32LinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, int parameter_count,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
return LH::GetJSCallDescriptor(zone, is_osr, parameter_count, flags);
}

View File

@ -410,8 +410,8 @@ bool JSGenericLowering::TryLowerDirectJSCall(Node* node) {
context = jsgraph()->HeapConstant(Handle<Context>(function->context()));
}
node->ReplaceInput(index, context);
CallDescriptor* desc = linkage()->GetJSCallDescriptor(
jsgraph()->zone(), 1 + arg_count, FlagsForNode(node));
CallDescriptor* desc =
linkage()->GetJSCallDescriptor(1 + arg_count, FlagsForNode(node));
PatchOperator(node, common()->Call(desc));
return true;
}

View File

@ -29,7 +29,8 @@ class LinkageHelper {
}
// TODO(turbofan): cache call descriptors for JSFunction calls.
static CallDescriptor* GetJSCallDescriptor(Zone* zone, int js_parameter_count,
static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
int js_parameter_count,
CallDescriptor::Flags flags) {
const size_t return_count = 1;
const size_t context_count = 1;
@ -56,7 +57,12 @@ class LinkageHelper {
// The target for JS function calls is the JSFunction object.
MachineType target_type = kMachAnyTagged;
LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg());
// Unoptimized code doesn't preserve the JSCallFunctionReg, so expect the
// closure on the stack.
LinkageLocation target_loc =
is_osr ? stackloc(Linkage::kJSFunctionCallClosureParamIndex -
js_parameter_count)
: regloc(LinkageTraits::JSCallFunctionReg());
return new (zone) CallDescriptor( // --
CallDescriptor::kCallJSFunction, // kind
target_type, // target MachineType

View File

@ -42,14 +42,16 @@ CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) {
if (info->function() != NULL) {
// If we already have the function literal, use the number of parameters
// plus the receiver.
return GetJSCallDescriptor(zone, 1 + info->function()->parameter_count(),
return GetJSCallDescriptor(zone, info->is_osr(),
1 + info->function()->parameter_count(),
CallDescriptor::kNoFlags);
}
if (!info->closure().is_null()) {
// If we are compiling a JS function, use a JS call descriptor,
// plus the receiver.
SharedFunctionInfo* shared = info->closure()->shared();
return GetJSCallDescriptor(zone, 1 + shared->formal_parameter_count(),
return GetJSCallDescriptor(zone, info->is_osr(),
1 + shared->formal_parameter_count(),
CallDescriptor::kNoFlags);
}
if (info->code_stub() != NULL) {
@ -94,7 +96,7 @@ FrameOffset Linkage::GetFrameOffset(int spill_slot, Frame* frame,
CallDescriptor* Linkage::GetJSCallDescriptor(
int parameter_count, CallDescriptor::Flags flags) const {
return GetJSCallDescriptor(zone_, parameter_count, flags);
return GetJSCallDescriptor(zone_, false, parameter_count, flags);
}
@ -232,7 +234,7 @@ bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
// Provide unimplemented methods on unsupported architectures, to at least link.
//==============================================================================
#if !V8_TURBOFAN_BACKEND
CallDescriptor* Linkage::GetJSCallDescriptor(Isolate* isolate, Zone* zone,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
UNIMPLEMENTED();
@ -247,17 +249,17 @@ LinkageLocation Linkage::GetOsrValueLocation(int index) const {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
Zone* zone, Runtime::FunctionId function, int parameter_count,
Operator::Properties properties) {
UNIMPLEMENTED();
return NULL;
}
CallDescriptor* Linkage::GetStubCallDescriptor(
const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Operator::Properties properties,
Zone* zone) {
Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
int stack_parameter_count, CallDescriptor::Flags flags,
Operator::Properties properties) {
UNIMPLEMENTED();
return NULL;
}

View File

@ -185,7 +185,8 @@ class Linkage : public ZoneObject {
CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
CallDescriptor* GetJSCallDescriptor(int parameter_count,
CallDescriptor::Flags flags) const;
static CallDescriptor* GetJSCallDescriptor(Zone* zone, int parameter_count,
static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags);
CallDescriptor* GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
@ -240,6 +241,9 @@ class Linkage : public ZoneObject {
// Get the location where an incoming OSR value is stored.
LinkageLocation GetOsrValueLocation(int index) const;
// A special parameter index for JSCalls that represents the closure.
static const int kJSFunctionCallClosureParamIndex = -1;
private:
Isolate* isolate_;
Zone* const zone_;

View File

@ -35,9 +35,10 @@ struct MipsLinkageHelperTraits {
typedef LinkageHelper<MipsLinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, int parameter_count,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
return LH::GetJSCallDescriptor(zone, is_osr, parameter_count, flags);
}

View File

@ -35,9 +35,10 @@ struct MipsLinkageHelperTraits {
typedef LinkageHelper<MipsLinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, int parameter_count,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
return LH::GetJSCallDescriptor(zone, is_osr, parameter_count, flags);
}

View File

@ -99,8 +99,8 @@ Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
Node* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
Node* context, Node* frame_state) {
CallDescriptor* descriptor =
Linkage::GetJSCallDescriptor(zone(), 1, CallDescriptor::kNeedsFrameState);
CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(
zone(), false, 1, CallDescriptor::kNeedsFrameState);
Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
context, frame_state);
schedule()->AddNode(CurrentBlock(), call);

View File

@ -49,9 +49,10 @@ struct X64LinkageHelperTraits {
typedef LinkageHelper<X64LinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, int parameter_count,
CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
int parameter_count,
CallDescriptor::Flags flags) {
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
return LH::GetJSCallDescriptor(zone, is_osr, parameter_count, flags);
}

View File

@ -0,0 +1,61 @@
// 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: --use-osr --turbo-osr
function foo(a) {
var sum = 0;
var inc = a ? 100 : 200;
for (var i = 0; i < 100000; i++) {
sum += inc;
}
return sum + inc;
}
function bar(a) {
var sum = 0;
var inc = a ? 100 : 200;
var x = a ? 5 : 6;
var y = a ? 7 : 8;
for (var i = 0; i < 100000; i++) {
sum += inc;
}
return sum ? x : y;
}
function baz(a) {
var limit = a ? 100001 : 100002;
var r = 1;
var x = a ? 1 : 2;
var y = a ? 3 : 4;
for (var i = 0; i < limit; i++) {
r = r * -1;
}
return r > 0 ? x == y : x != y;
}
function qux(a) {
var limit = a ? 100001 : 100002;
var r = 1;
var x = a ? 1 : 2;
var y = a ? 3 : 4;
for (var i = 0; i < limit; i++) {
r = r * -1;
}
var w = r > 0 ? x : y;
var z = r > 0 ? y : x;
return w === z;
}
function test(func, tv, fv) {
assertEquals(tv, func(true));
assertEquals(fv, func(false));
assertEquals(tv, func(true));
assertEquals(fv, func(false));
}
test(foo, 10000100, 20000200);
test(bar, 5, 6);
test(baz, true, false);
test(qux, false, false);

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --use-osr --turbo-osr
// Flags: --use-osr --turbo-osr
function f(a) {
var sum = 0;

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --use-osr --turbo-osr
// Flags: --use-osr --turbo-osr
function f(a) {
var sum = 0;

View File

@ -0,0 +1,33 @@
// 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: --use-osr --turbo-osr
function id(f) { return f; }
function foo() {
var sum = 0;
var r = id(foo);
for (var i = 0; i < 100000; i++) {
sum += i;
}
return foo == r;
}
assertEquals(true, foo());
assertEquals(true, foo());
assertEquals(true, foo());
function bar() {
var sum = 0;
for (var i = 0; i < 90000; i++) {
sum += i;
}
return id(bar,sum);
}
assertEquals(bar, bar());
assertEquals(bar, bar());
assertEquals(bar, bar());

View File

@ -0,0 +1,28 @@
// 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: --use-osr --turbo-osr
function id(f) { return f; }
var x = (function foo() {
var sum = 0;
var r = id(foo);
for (var i = 0; i < 100000; i++) {
sum += i;
}
return foo == r;
})();
assertEquals(true, x);
var x = (function bar() {
var sum = 0;
for (var i = 0; i < 90000; i++) {
sum += i;
}
return bar;
})();
assertEquals("function", typeof x);

View File

@ -0,0 +1,31 @@
// 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: --use-osr --turbo-osr
function foo() {
var sum = 0;
for (var i = 0; i < 100000; i++) {
sum += i;
}
return function() { return sum; }
}
assertEquals(4999950000, foo()());
assertEquals(4999950000, foo()());
assertEquals(4999950000, foo()());
function bar() {
var sum = 0;
var ret = 0;
for (var i = 0; i < 90000; i++) {
sum += i;
if (i == 0) ret = function() { return sum; }
}
return ret;
}
assertEquals(4049955000, bar()());
assertEquals(4049955000, bar()());
assertEquals(4049955000, bar()());

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --use-osr --turbo-osr
// Flags: --use-osr --turbo-osr
function f() {
var sum = 0;

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --use-osr --turbo-osr
// Flags: --use-osr --turbo-osr
function f() {
var sum = 0;

View File

@ -0,0 +1,54 @@
// 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 --use-osr --turbo-osr
function id(f) { return f; }
function foo(a) {
var r = /\0/;
for (var i = 0; i < 10; i++) {
if (a) %OptimizeFunctionOnNextCall(foo, "osr");
}
return r;
}
function bar(a) {
for (var i = 0; i < 10; i++) {
if (a) %OptimizeFunctionOnNextCall(bar, "osr");
var r = /\0/;
}
return r;
}
function baz(a) {
for (var i = 0; i < 10; i++) {
if (a) %OptimizeFunctionOnNextCall(baz, "osr");
}
return /\0/;
}
function qux(a) {
for (var i = 0; i < 10; i++) {
if (i > 5 && a) {
%OptimizeFunctionOnNextCall(qux, "osr");
} else {
var r = /\0/;
}
}
return r;
}
function test(f) {
// Test the reference equality of regex's created in OSR'd function.
var x = f(false);
assertEquals(x, f(true));
assertEquals(x, f(true));
assertEquals(x, f(true));
}
test(foo);
test(bar);
test(baz);
test(qux);