Now with more checkings! Skip the CallFunctionStub when the callee function can be statically determined.
R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/696223002 Cr-Commit-Position: refs/heads/master@{#25062} git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25062 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
498920f91c
commit
c62bb3e2eb
@ -35,8 +35,9 @@ struct ArmLinkageHelperTraits {
|
||||
|
||||
typedef LinkageHelper<ArmLinkageHelperTraits> LH;
|
||||
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count);
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
|
||||
CallDescriptor::Flags flags) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,8 +35,9 @@ struct Arm64LinkageHelperTraits {
|
||||
|
||||
typedef LinkageHelper<Arm64LinkageHelperTraits> LH;
|
||||
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count);
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
|
||||
CallDescriptor::Flags flags) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,8 +30,9 @@ struct IA32LinkageHelperTraits {
|
||||
|
||||
typedef LinkageHelper<IA32LinkageHelperTraits> LH;
|
||||
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count);
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
|
||||
CallDescriptor::Flags flags) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/compiler/js-generic-lowering.h"
|
||||
#include "src/compiler/machine-operator.h"
|
||||
#include "src/compiler/node-aux-data-inl.h"
|
||||
#include "src/compiler/node-matchers.h"
|
||||
#include "src/compiler/node-properties-inl.h"
|
||||
#include "src/unique.h"
|
||||
|
||||
@ -405,9 +406,51 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
void JSGenericLowering::LowerJSCallFunction(Node* node) {
|
||||
bool JSGenericLowering::TryLowerDirectJSCall(Node* node) {
|
||||
// Lower to a direct call to a constant JSFunction if legal.
|
||||
const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
|
||||
CallFunctionStub stub(isolate(), static_cast<int>(p.arity() - 2), p.flags());
|
||||
int arg_count = static_cast<int>(p.arity() - 2);
|
||||
|
||||
// Check the function is a constant and is really a JSFunction.
|
||||
HeapObjectMatcher<Object> function_const(node->InputAt(0));
|
||||
if (!function_const.HasValue()) return false; // not a constant.
|
||||
Handle<Object> func = function_const.Value().handle();
|
||||
if (!func->IsJSFunction()) return false; // not a function.
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(func);
|
||||
if (arg_count != function->shared()->formal_parameter_count()) return false;
|
||||
|
||||
// Check the receiver doesn't need to be wrapped.
|
||||
Node* receiver = node->InputAt(1);
|
||||
if (!NodeProperties::IsTyped(receiver)) return false;
|
||||
Type* ok_receiver = Type::Union(Type::Undefined(), Type::Receiver(), zone());
|
||||
if (!NodeProperties::GetBounds(receiver).upper->Is(ok_receiver)) return false;
|
||||
|
||||
int index = NodeProperties::FirstContextIndex(node);
|
||||
|
||||
// TODO(titzer): total hack to share function context constants.
|
||||
// Remove this when the JSGraph canonicalizes heap constants.
|
||||
Node* context = node->InputAt(index);
|
||||
HeapObjectMatcher<Context> context_const(context);
|
||||
if (!context_const.HasValue() ||
|
||||
*(context_const.Value().handle()) != function->context()) {
|
||||
context = jsgraph()->HeapConstant(Handle<Context>(function->context()));
|
||||
}
|
||||
node->ReplaceInput(index, context);
|
||||
CallDescriptor* desc = linkage()->GetJSCallDescriptor(
|
||||
1 + arg_count, jsgraph()->zone(), FlagsForNode(node));
|
||||
PatchOperator(node, common()->Call(desc));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void JSGenericLowering::LowerJSCallFunction(Node* node) {
|
||||
// Fast case: call function directly.
|
||||
if (TryLowerDirectJSCall(node)) return;
|
||||
|
||||
// General case: CallFunctionStub.
|
||||
const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
|
||||
int arg_count = static_cast<int>(p.arity() - 2);
|
||||
CallFunctionStub stub(isolate(), arg_count, p.flags());
|
||||
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
|
||||
CallDescriptor* desc = linkage()->GetStubCallDescriptor(
|
||||
d, static_cast<int>(p.arity() - 1), FlagsForNode(node));
|
||||
|
@ -66,6 +66,8 @@ class JSGenericLowering : public Reducer {
|
||||
CompilationInfo* info_;
|
||||
JSGraph* jsgraph_;
|
||||
Linkage* linkage_;
|
||||
|
||||
bool TryLowerDirectJSCall(Node* node);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -28,8 +28,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, int js_parameter_count,
|
||||
CallDescriptor::Flags flags) {
|
||||
const size_t return_count = 1;
|
||||
const size_t context_count = 1;
|
||||
const size_t parameter_count = js_parameter_count + context_count;
|
||||
@ -56,16 +56,17 @@ class LinkageHelper {
|
||||
// The target for JS function calls is the JSFunction object.
|
||||
MachineType target_type = kMachAnyTagged;
|
||||
LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg());
|
||||
return new (zone) CallDescriptor(CallDescriptor::kCallJSFunction, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
types.Build(), // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
js_parameter_count, // js_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
kNoCalleeSaved, // callee-saved
|
||||
CallDescriptor::kNeedsFrameState, // flags
|
||||
"js-call");
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallJSFunction, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
types.Build(), // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
js_parameter_count, // js_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
kNoCalleeSaved, // callee-saved
|
||||
flags, // flags
|
||||
"js-call");
|
||||
}
|
||||
|
||||
|
||||
@ -116,16 +117,17 @@ class LinkageHelper {
|
||||
// The target for runtime calls is a code object.
|
||||
MachineType target_type = kMachAnyTagged;
|
||||
LinkageLocation target_loc = LinkageLocation::AnyRegister();
|
||||
return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
types.Build(), // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
js_parameter_count, // js_parameter_count
|
||||
properties, // properties
|
||||
kNoCalleeSaved, // callee-saved
|
||||
flags, // flags
|
||||
function->name); // debug name
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
types.Build(), // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
js_parameter_count, // js_parameter_count
|
||||
properties, // properties
|
||||
kNoCalleeSaved, // callee-saved
|
||||
flags, // flags
|
||||
function->name); // debug name
|
||||
}
|
||||
|
||||
|
||||
@ -169,16 +171,17 @@ class LinkageHelper {
|
||||
// The target for stub calls is a code object.
|
||||
MachineType target_type = kMachAnyTagged;
|
||||
LinkageLocation target_loc = LinkageLocation::AnyRegister();
|
||||
return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
types.Build(), // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
js_parameter_count, // js_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
kNoCalleeSaved, // callee-saved registers
|
||||
flags, // flags
|
||||
descriptor.DebugName(zone->isolate()));
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
types.Build(), // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
js_parameter_count, // js_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
kNoCalleeSaved, // callee-saved registers
|
||||
flags, // flags
|
||||
descriptor.DebugName(zone->isolate()));
|
||||
}
|
||||
|
||||
static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
|
||||
@ -201,15 +204,16 @@ class LinkageHelper {
|
||||
// The target for C calls is always an address (i.e. machine pointer).
|
||||
MachineType target_type = kMachPtr;
|
||||
LinkageLocation target_loc = LinkageLocation::AnyRegister();
|
||||
return new (zone) CallDescriptor(CallDescriptor::kCallAddress, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
msig, // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
0, // js_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
LinkageTraits::CCalleeSaveRegisters(),
|
||||
CallDescriptor::kNoFlags, "c-call");
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallAddress, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
msig, // machine_sig
|
||||
locations.Build(), // location_sig
|
||||
0, // js_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
LinkageTraits::CCalleeSaveRegisters(), CallDescriptor::kNoFlags,
|
||||
"c-call");
|
||||
}
|
||||
|
||||
static LinkageLocation regloc(Register reg) {
|
||||
|
@ -42,13 +42,15 @@ 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(1 + info->function()->parameter_count(), zone);
|
||||
return GetJSCallDescriptor(1 + info->function()->parameter_count(), zone,
|
||||
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(1 + shared->formal_parameter_count(), zone);
|
||||
return GetJSCallDescriptor(1 + shared->formal_parameter_count(), zone,
|
||||
CallDescriptor::kNoFlags);
|
||||
}
|
||||
if (info->code_stub() != NULL) {
|
||||
// Use the code stub interface descriptor.
|
||||
@ -88,8 +90,9 @@ FrameOffset Linkage::GetFrameOffset(int spill_slot, Frame* frame,
|
||||
}
|
||||
|
||||
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count) const {
|
||||
return GetJSCallDescriptor(parameter_count, zone_);
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(
|
||||
int parameter_count, CallDescriptor::Flags flags) const {
|
||||
return GetJSCallDescriptor(parameter_count, zone_, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -174,8 +174,10 @@ class Linkage : public ZoneObject {
|
||||
// The call descriptor for this compilation unit describes the locations
|
||||
// of incoming parameters and the outgoing return value(s).
|
||||
CallDescriptor* GetIncomingDescriptor() const { return incoming_; }
|
||||
CallDescriptor* GetJSCallDescriptor(int parameter_count) const;
|
||||
static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone);
|
||||
CallDescriptor* GetJSCallDescriptor(int parameter_count,
|
||||
CallDescriptor::Flags flags) const;
|
||||
static CallDescriptor* GetJSCallDescriptor(int parameter_count, Zone* zone,
|
||||
CallDescriptor::Flags flags);
|
||||
CallDescriptor* GetRuntimeCallDescriptor(
|
||||
Runtime::FunctionId function, int parameter_count,
|
||||
Operator::Properties properties) const;
|
||||
|
@ -35,8 +35,9 @@ struct MipsLinkageHelperTraits {
|
||||
|
||||
typedef LinkageHelper<MipsLinkageHelperTraits> LH;
|
||||
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count);
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
|
||||
CallDescriptor::Flags flags) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,7 +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(1, zone());
|
||||
CallDescriptor* descriptor =
|
||||
Linkage::GetJSCallDescriptor(1, zone(), CallDescriptor::kNeedsFrameState);
|
||||
Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
|
||||
context, frame_state);
|
||||
schedule()->AddNode(CurrentBlock(), call);
|
||||
|
@ -49,8 +49,9 @@ struct X64LinkageHelperTraits {
|
||||
|
||||
typedef LinkageHelper<X64LinkageHelperTraits> LH;
|
||||
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count);
|
||||
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
|
||||
CallDescriptor::Flags flags) {
|
||||
return LH::GetJSCallDescriptor(zone, parameter_count, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,7 +90,8 @@ TEST(TestLinkageJSCall) {
|
||||
Linkage linkage(info.zone(), &info);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
CallDescriptor* descriptor = linkage.GetJSCallDescriptor(i);
|
||||
CallDescriptor* descriptor =
|
||||
linkage.GetJSCallDescriptor(i, CallDescriptor::kNoFlags);
|
||||
CHECK_NE(NULL, descriptor);
|
||||
CHECK_EQ(i, descriptor->JSParameterCount());
|
||||
CHECK_EQ(1, descriptor->ReturnCount());
|
||||
|
Loading…
Reference in New Issue
Block a user