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);
}
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);
}
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);
}
#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"
}
+bool JSGenericLowering::TryLowerDirectJSCall(Node* node) {
+ // Lower to a direct call to a constant JSFunction if legal.
+ const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
+ 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());
- CallFunctionStub stub(isolate(), static_cast<int>(p.arity() - 2), p.flags());
+ 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));
CompilationInfo* info_;
JSGraph* jsgraph_;
Linkage* linkage_;
+
+ bool TryLowerDirectJSCall(Node* node);
};
} // namespace compiler
}
// 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;
// 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");
}
// 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
}
// 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,
// 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) {
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.
}
-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);
}
// 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;
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);
}
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);
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);
}
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());