[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:
parent
32fe247d91
commit
e25a0f7e4e
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
61
test/mjsunit/compiler/osr-follow.js
Normal file
61
test/mjsunit/compiler/osr-follow.js
Normal 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);
|
@ -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;
|
||||
|
@ -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;
|
||||
|
33
test/mjsunit/compiler/osr-function-id.js
Normal file
33
test/mjsunit/compiler/osr-function-id.js
Normal 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());
|
28
test/mjsunit/compiler/osr-function-id2.js
Normal file
28
test/mjsunit/compiler/osr-function-id2.js
Normal 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);
|
31
test/mjsunit/compiler/osr-function.js
Normal file
31
test/mjsunit/compiler/osr-function.js
Normal 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()());
|
@ -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;
|
||||
|
@ -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;
|
||||
|
54
test/mjsunit/compiler/osr-regex-id.js
Normal file
54
test/mjsunit/compiler/osr-regex-id.js
Normal 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);
|
Loading…
Reference in New Issue
Block a user