Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc
index fc6b19e..2eef929 100644
--- a/src/compiler/linkage.cc
+++ b/src/compiler/linkage.cc
@@ -2,17 +2,55 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/ast/scopes.h"
#include "src/code-stubs.h"
#include "src/compiler.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/frame.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node.h"
+#include "src/compiler/osr.h"
#include "src/compiler/pipeline.h"
-#include "src/scopes.h"
namespace v8 {
namespace internal {
namespace compiler {
+namespace {
+LinkageLocation regloc(Register reg) {
+ return LinkageLocation::ForRegister(reg.code());
+}
+
+
+MachineType reptyp(Representation representation) {
+ switch (representation.kind()) {
+ case Representation::kInteger8:
+ return MachineType::Int8();
+ case Representation::kUInteger8:
+ return MachineType::Uint8();
+ case Representation::kInteger16:
+ return MachineType::Int16();
+ case Representation::kUInteger16:
+ return MachineType::Uint16();
+ case Representation::kInteger32:
+ return MachineType::Int32();
+ case Representation::kSmi:
+ case Representation::kTagged:
+ case Representation::kHeapObject:
+ return MachineType::AnyTagged();
+ case Representation::kDouble:
+ return MachineType::Float64();
+ case Representation::kExternal:
+ return MachineType::Pointer();
+ case Representation::kNone:
+ case Representation::kNumRepresentations:
+ break;
+ }
+ UNREACHABLE();
+ return MachineType::None();
+}
+} // namespace
+
std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) {
switch (k) {
@@ -25,6 +63,9 @@
case CallDescriptor::kCallAddress:
os << "Addr";
break;
+ case CallDescriptor::kLazyBailout:
+ os << "LazyBail";
+ break;
}
return os;
}
@@ -33,226 +74,466 @@
std::ostream& operator<<(std::ostream& os, const CallDescriptor& d) {
// TODO(svenpanne) Output properties etc. and be less cryptic.
return os << d.kind() << ":" << d.debug_name() << ":r" << d.ReturnCount()
- << "j" << d.JSParameterCount() << "i" << d.InputCount() << "f"
- << d.FrameStateCount();
+ << "s" << d.StackParameterCount() << "i" << d.InputCount() << "f"
+ << d.FrameStateCount() << "t" << d.SupportsTailCalls();
+}
+
+
+bool CallDescriptor::HasSameReturnLocationsAs(
+ const CallDescriptor* other) const {
+ if (ReturnCount() != other->ReturnCount()) return false;
+ for (size_t i = 0; i < ReturnCount(); ++i) {
+ if (GetReturnLocation(i) != other->GetReturnLocation(i)) return false;
+ }
+ return true;
+}
+
+
+bool CallDescriptor::CanTailCall(const Node* node,
+ int* stack_param_delta) const {
+ CallDescriptor const* other = OpParameter<CallDescriptor const*>(node);
+ size_t current_input = 0;
+ size_t other_input = 0;
+ *stack_param_delta = 0;
+ bool more_other = true;
+ bool more_this = true;
+ while (more_other || more_this) {
+ if (other_input < other->InputCount()) {
+ if (!other->GetInputLocation(other_input).IsRegister()) {
+ (*stack_param_delta)--;
+ }
+ } else {
+ more_other = false;
+ }
+ if (current_input < InputCount()) {
+ if (!GetInputLocation(current_input).IsRegister()) {
+ (*stack_param_delta)++;
+ }
+ } else {
+ more_this = false;
+ }
+ ++current_input;
+ ++other_input;
+ }
+ return HasSameReturnLocationsAs(OpParameter<CallDescriptor const*>(node));
}
CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) {
- if (info->function() != NULL) {
+ if (info->code_stub() != nullptr) {
+ // Use the code stub interface descriptor.
+ CodeStub* stub = info->code_stub();
+ CallInterfaceDescriptor descriptor = stub->GetCallInterfaceDescriptor();
+ return GetStubCallDescriptor(
+ info->isolate(), zone, descriptor, stub->GetStackParameterCount(),
+ CallDescriptor::kNoFlags, Operator::kNoProperties);
+ }
+ if (info->has_literal()) {
// 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(zone, info->is_osr(),
+ 1 + info->literal()->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(1 + shared->formal_parameter_count(), zone,
+ return GetJSCallDescriptor(zone, info->is_osr(),
+ 1 + shared->internal_formal_parameter_count(),
CallDescriptor::kNoFlags);
}
- if (info->code_stub() != NULL) {
- // Use the code stub interface descriptor.
- CallInterfaceDescriptor descriptor =
- info->code_stub()->GetCallInterfaceDescriptor();
- return GetStubCallDescriptor(descriptor, 0, CallDescriptor::kNoFlags,
- Operator::kNoProperties, zone);
- }
- return NULL; // TODO(titzer): ?
-}
-
-
-FrameOffset Linkage::GetFrameOffset(int spill_slot, Frame* frame,
- int extra) const {
- if (frame->GetSpillSlotCount() > 0 || incoming_->IsJSFunctionCall() ||
- incoming_->kind() == CallDescriptor::kCallAddress) {
- int offset;
- int register_save_area_size = frame->GetRegisterSaveAreaSize();
- if (spill_slot >= 0) {
- // Local or spill slot. Skip the frame pointer, function, and
- // context in the fixed part of the frame.
- offset =
- -(spill_slot + 1) * kPointerSize - register_save_area_size + extra;
- } else {
- // Incoming parameter. Skip the return address.
- offset = -(spill_slot + 1) * kPointerSize + kFPOnStackSize +
- kPCOnStackSize + extra;
- }
- return FrameOffset::FromFramePointer(offset);
- } else {
- // No frame. Retrieve all parameters relative to stack pointer.
- DCHECK(spill_slot < 0); // Must be a parameter.
- int register_save_area_size = frame->GetRegisterSaveAreaSize();
- int offset = register_save_area_size - (spill_slot + 1) * kPointerSize +
- kPCOnStackSize + extra;
- return FrameOffset::FromStackPointer(offset);
- }
-}
-
-
-CallDescriptor* Linkage::GetJSCallDescriptor(
- int parameter_count, CallDescriptor::Flags flags) const {
- return GetJSCallDescriptor(parameter_count, zone_, flags);
-}
-
-
-CallDescriptor* Linkage::GetRuntimeCallDescriptor(
- Runtime::FunctionId function, int parameter_count,
- Operator::Properties properties) const {
- return GetRuntimeCallDescriptor(function, parameter_count, properties, zone_);
-}
-
-
-CallDescriptor* Linkage::GetStubCallDescriptor(
- const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
- CallDescriptor::Flags flags, Operator::Properties properties) const {
- return GetStubCallDescriptor(descriptor, stack_parameter_count, flags,
- properties, zone_);
+ return nullptr; // TODO(titzer): ?
}
// static
-bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
- if (!FLAG_turbo_deoptimization) {
- return false;
- }
- // TODO(jarin) At the moment, we only add frame state for
- // few chosen runtime functions.
+int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
+ // Most runtime functions need a FrameState. A few chosen ones that we know
+ // not to call into arbitrary JavaScript, not to throw, and not to deoptimize
+ // are blacklisted here and can be called without a FrameState.
switch (function) {
- case Runtime::kApply:
- case Runtime::kArrayBufferNeuter:
- case Runtime::kArrayConcat:
- case Runtime::kBasicJSONStringify:
- case Runtime::kCheckExecutionState:
- case Runtime::kCollectStackTrace:
- case Runtime::kCompileLazy:
- case Runtime::kCompileOptimized:
- case Runtime::kCompileString:
- case Runtime::kCreateObjectLiteral:
- case Runtime::kDebugBreak:
- case Runtime::kDataViewSetInt8:
- case Runtime::kDataViewSetUint8:
- case Runtime::kDataViewSetInt16:
- case Runtime::kDataViewSetUint16:
- case Runtime::kDataViewSetInt32:
- case Runtime::kDataViewSetUint32:
- case Runtime::kDataViewSetFloat32:
- case Runtime::kDataViewSetFloat64:
- case Runtime::kDataViewGetInt8:
- case Runtime::kDataViewGetUint8:
- case Runtime::kDataViewGetInt16:
- case Runtime::kDataViewGetUint16:
- case Runtime::kDataViewGetInt32:
- case Runtime::kDataViewGetUint32:
- case Runtime::kDataViewGetFloat32:
- case Runtime::kDataViewGetFloat64:
- case Runtime::kDebugEvaluate:
- case Runtime::kDebugEvaluateGlobal:
- case Runtime::kDebugGetLoadedScripts:
- case Runtime::kDebugGetPropertyDetails:
- case Runtime::kDebugPromiseEvent:
- case Runtime::kDefineAccessorPropertyUnchecked:
- case Runtime::kDefineDataPropertyUnchecked:
- case Runtime::kDeleteProperty:
- case Runtime::kDeoptimizeFunction:
- case Runtime::kFunctionBindArguments:
- case Runtime::kGetDefaultReceiver:
- case Runtime::kGetFrameCount:
- case Runtime::kGetOwnProperty:
- case Runtime::kGetOwnPropertyNames:
- case Runtime::kGetPropertyNamesFast:
- case Runtime::kGetPrototype:
+ case Runtime::kAllocateInTargetSpace:
+ case Runtime::kCreateIterResultObject:
+ case Runtime::kDefineClassMethod: // TODO(jarin): Is it safe?
+ case Runtime::kDefineGetterPropertyUnchecked: // TODO(jarin): Is it safe?
+ case Runtime::kDefineSetterPropertyUnchecked: // TODO(jarin): Is it safe?
+ case Runtime::kFinalizeClassDefinition: // TODO(conradw): Is it safe?
+ case Runtime::kForInDone:
+ case Runtime::kForInStep:
+ case Runtime::kGetSuperConstructor:
+ case Runtime::kNewClosure:
+ case Runtime::kNewClosure_Tenured:
+ case Runtime::kNewFunctionContext:
+ case Runtime::kPushBlockContext:
+ case Runtime::kPushCatchContext:
+ case Runtime::kReThrow:
+ case Runtime::kStringCompare:
+ case Runtime::kStringEquals:
+ case Runtime::kToFastProperties: // TODO(jarin): Is it safe?
+ case Runtime::kTraceEnter:
+ case Runtime::kTraceExit:
+ return 0;
case Runtime::kInlineArguments:
- case Runtime::kInlineCallFunction:
- case Runtime::kInlineDateField:
+ case Runtime::kInlineArgumentsLength:
+ case Runtime::kInlineGetPrototype:
+ case Runtime::kInlineRegExpConstructResult:
case Runtime::kInlineRegExpExec:
- case Runtime::kInternalSetPrototype:
- case Runtime::kInterrupt:
- case Runtime::kIsPropertyEnumerable:
- case Runtime::kIsSloppyModeFunction:
- case Runtime::kLiveEditGatherCompileInfo:
- case Runtime::kLoadLookupSlot:
- case Runtime::kLoadLookupSlotNoReferenceError:
- case Runtime::kMaterializeRegExpLiteral:
- case Runtime::kNewObject:
- case Runtime::kNewObjectFromBound:
- case Runtime::kNewObjectWithAllocationSite:
- case Runtime::kObjectFreeze:
- case Runtime::kOwnKeys:
- case Runtime::kParseJson:
- case Runtime::kPrepareStep:
- case Runtime::kPreventExtensions:
- case Runtime::kPromiseRejectEvent:
- case Runtime::kPromiseRevokeReject:
- case Runtime::kRegExpInitializeAndCompile:
- case Runtime::kRegExpExecMultiple:
- case Runtime::kResolvePossiblyDirectEval:
- case Runtime::kRunMicrotasks:
- case Runtime::kSetPrototype:
- case Runtime::kSetScriptBreakPoint:
- case Runtime::kSparseJoinWithSeparator:
- case Runtime::kStackGuard:
- case Runtime::kStoreKeyedToSuper_Sloppy:
- case Runtime::kStoreKeyedToSuper_Strict:
- case Runtime::kStoreToSuper_Sloppy:
- case Runtime::kStoreToSuper_Strict:
- case Runtime::kStoreLookupSlot:
- case Runtime::kStringBuilderConcat:
- case Runtime::kStringBuilderJoin:
- case Runtime::kStringMatch:
- case Runtime::kStringReplaceGlobalRegExpWithString:
- case Runtime::kThrowNonMethodError:
- case Runtime::kThrowNotDateError:
- case Runtime::kThrowReferenceError:
- case Runtime::kThrowUnsupportedSuperError:
- case Runtime::kThrow:
- case Runtime::kTypedArraySetFastCases:
- case Runtime::kTypedArrayInitializeFromArrayLike:
-#ifdef V8_I18N_SUPPORT
- case Runtime::kGetImplFromInitializedIntlObject:
-#endif
- return true;
+ case Runtime::kInlineSubString:
+ case Runtime::kInlineToInteger:
+ case Runtime::kInlineToLength:
+ case Runtime::kInlineToName:
+ case Runtime::kInlineToNumber:
+ case Runtime::kInlineToObject:
+ case Runtime::kInlineToPrimitive_Number:
+ case Runtime::kInlineToPrimitive_String:
+ case Runtime::kInlineToPrimitive:
+ case Runtime::kInlineToString:
+ return 1;
+ case Runtime::kInlineCall:
+ case Runtime::kInlineTailCall:
+ case Runtime::kInlineDeoptimizeNow:
+ case Runtime::kInlineThrowNotDateError:
+ return 2;
default:
- return false;
+ break;
}
+
+ // Most inlined runtime functions (except the ones listed above) can be called
+ // without a FrameState or will be lowered by JSIntrinsicLowering internally.
+ const Runtime::Function* const f = Runtime::FunctionForId(function);
+ if (f->intrinsic_type == Runtime::IntrinsicType::INLINE) return 0;
+
+ return 1;
}
-//==============================================================================
-// Provide unimplemented methods on unsupported architectures, to at least link.
-//==============================================================================
-#if !V8_TURBOFAN_BACKEND
-CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone,
- CallDescriptor::Flags flags) {
- UNIMPLEMENTED();
- return NULL;
+bool CallDescriptor::UsesOnlyRegisters() const {
+ for (size_t i = 0; i < InputCount(); ++i) {
+ if (!GetInputLocation(i).IsRegister()) return false;
+ }
+ for (size_t i = 0; i < ReturnCount(); ++i) {
+ if (!GetReturnLocation(i).IsRegister()) return false;
+ }
+ return true;
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
- Runtime::FunctionId function, int parameter_count,
- Operator::Properties properties, Zone* zone) {
- UNIMPLEMENTED();
- return NULL;
+ Zone* zone, Runtime::FunctionId function_id, int js_parameter_count,
+ Operator::Properties properties, CallDescriptor::Flags flags) {
+ const size_t function_count = 1;
+ const size_t num_args_count = 1;
+ const size_t context_count = 1;
+ const size_t parameter_count = function_count +
+ static_cast<size_t>(js_parameter_count) +
+ num_args_count + context_count;
+
+ const Runtime::Function* function = Runtime::FunctionForId(function_id);
+ const size_t return_count = static_cast<size_t>(function->result_size);
+
+ LocationSignature::Builder locations(zone, return_count, parameter_count);
+ MachineSignature::Builder types(zone, return_count, parameter_count);
+
+ // Add returns.
+ if (locations.return_count_ > 0) {
+ locations.AddReturn(regloc(kReturnRegister0));
+ }
+ if (locations.return_count_ > 1) {
+ locations.AddReturn(regloc(kReturnRegister1));
+ }
+ for (size_t i = 0; i < return_count; i++) {
+ types.AddReturn(MachineType::AnyTagged());
+ }
+
+ // All parameters to the runtime call go on the stack.
+ for (int i = 0; i < js_parameter_count; i++) {
+ locations.AddParam(
+ LinkageLocation::ForCallerFrameSlot(i - js_parameter_count));
+ types.AddParam(MachineType::AnyTagged());
+ }
+ // Add runtime function itself.
+ locations.AddParam(regloc(kRuntimeCallFunctionRegister));
+ types.AddParam(MachineType::AnyTagged());
+
+ // Add runtime call argument count.
+ locations.AddParam(regloc(kRuntimeCallArgCountRegister));
+ types.AddParam(MachineType::Pointer());
+
+ // Add context.
+ locations.AddParam(regloc(kContextRegister));
+ types.AddParam(MachineType::AnyTagged());
+
+ if (Linkage::FrameStateInputCount(function_id) == 0) {
+ flags = static_cast<CallDescriptor::Flags>(
+ flags & ~CallDescriptor::kNeedsFrameState);
+ }
+
+ // The target for runtime calls is a code object.
+ MachineType target_type = MachineType::AnyTagged();
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ 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, // stack_parameter_count
+ properties, // properties
+ kNoCalleeSaved, // callee-saved
+ kNoCalleeSaved, // callee-saved fp
+ flags, // flags
+ function->name); // debug name
}
+CallDescriptor* Linkage::GetLazyBailoutDescriptor(Zone* zone) {
+ const size_t return_count = 0;
+ const size_t parameter_count = 0;
+
+ LocationSignature::Builder locations(zone, return_count, parameter_count);
+ MachineSignature::Builder types(zone, return_count, parameter_count);
+
+ // The target is ignored, but we need to give some values here.
+ MachineType target_type = MachineType::AnyTagged();
+ LinkageLocation target_loc = regloc(kJSFunctionRegister);
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kLazyBailout, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ types.Build(), // machine_sig
+ locations.Build(), // location_sig
+ 0, // stack_parameter_count
+ Operator::kNoThrow, // properties
+ kNoCalleeSaved, // callee-saved
+ kNoCalleeSaved, // callee-saved fp
+ CallDescriptor::kNeedsFrameState, // flags
+ "lazy-bailout");
+}
+
+
+CallDescriptor* Linkage::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;
+ const size_t new_target_count = 1;
+ const size_t num_args_count = 1;
+ const size_t parameter_count =
+ js_parameter_count + new_target_count + num_args_count + context_count;
+
+ LocationSignature::Builder locations(zone, return_count, parameter_count);
+ MachineSignature::Builder types(zone, return_count, parameter_count);
+
+ // All JS calls have exactly one return value.
+ locations.AddReturn(regloc(kReturnRegister0));
+ types.AddReturn(MachineType::AnyTagged());
+
+ // All parameters to JS calls go on the stack.
+ for (int i = 0; i < js_parameter_count; i++) {
+ int spill_slot_index = i - js_parameter_count;
+ locations.AddParam(LinkageLocation::ForCallerFrameSlot(spill_slot_index));
+ types.AddParam(MachineType::AnyTagged());
+ }
+
+ // Add JavaScript call new target value.
+ locations.AddParam(regloc(kJavaScriptCallNewTargetRegister));
+ types.AddParam(MachineType::AnyTagged());
+
+ // Add JavaScript call argument count.
+ locations.AddParam(regloc(kJavaScriptCallArgCountRegister));
+ types.AddParam(MachineType::Int32());
+
+ // Add context.
+ locations.AddParam(regloc(kContextRegister));
+ types.AddParam(MachineType::AnyTagged());
+
+ // The target for JS function calls is the JSFunction object.
+ MachineType target_type = MachineType::AnyTagged();
+ // TODO(titzer): When entering into an OSR function from unoptimized code,
+ // the JSFunction is not in a register, but it is on the stack in an
+ // unaddressable spill slot. We hack this in the OSR prologue. Fix.
+ LinkageLocation target_loc = regloc(kJSFunctionRegister);
+ 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, // stack_parameter_count
+ Operator::kNoProperties, // properties
+ kNoCalleeSaved, // callee-saved
+ kNoCalleeSaved, // callee-saved fp
+ CallDescriptor::kCanUseRoots | // flags
+ flags, // flags
+ "js-call");
+}
+
+
+CallDescriptor* Linkage::GetInterpreterDispatchDescriptor(Zone* zone) {
+ MachineSignature::Builder types(zone, 0, 6);
+ LocationSignature::Builder locations(zone, 0, 6);
+
+ // Add registers for fixed parameters passed via interpreter dispatch.
+ STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
+ types.AddParam(MachineType::AnyTagged());
+ locations.AddParam(regloc(kInterpreterAccumulatorRegister));
+
+ STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
+ types.AddParam(MachineType::Pointer());
+ locations.AddParam(regloc(kInterpreterRegisterFileRegister));
+
+ STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
+ types.AddParam(MachineType::IntPtr());
+ locations.AddParam(regloc(kInterpreterBytecodeOffsetRegister));
+
+ STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
+ types.AddParam(MachineType::AnyTagged());
+ locations.AddParam(regloc(kInterpreterBytecodeArrayRegister));
+
+ STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
+ types.AddParam(MachineType::Pointer());
+#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X87)
+ // TODO(rmcilroy): Make the context param the one spilled to the stack once
+ // Turbofan supports modified stack arguments in tail calls.
+ locations.AddParam(
+ LinkageLocation::ForCallerFrameSlot(kInterpreterDispatchTableSpillSlot));
+#else
+ locations.AddParam(regloc(kInterpreterDispatchTableRegister));
+#endif
+
+ STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
+ types.AddParam(MachineType::AnyTagged());
+ locations.AddParam(regloc(kContextRegister));
+
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallCodeObject, // kind
+ MachineType::None(), // target MachineType
+ target_loc, // target location
+ types.Build(), // machine_sig
+ locations.Build(), // location_sig
+ 0, // stack_parameter_count
+ Operator::kNoProperties, // properties
+ kNoCalleeSaved, // callee-saved registers
+ kNoCalleeSaved, // callee-saved fp regs
+ CallDescriptor::kSupportsTailCalls | // flags
+ CallDescriptor::kCanUseRoots, // flags
+ "interpreter-dispatch");
+}
+
+
+// TODO(all): Add support for return representations/locations to
+// CallInterfaceDescriptor.
+// TODO(turbofan): cache call descriptors for code stub calls.
CallDescriptor* Linkage::GetStubCallDescriptor(
- const CallInterfaceDescriptor& descriptor, int stack_parameter_count,
- CallDescriptor::Flags flags, Operator::Properties properties,
- Zone* zone) {
- UNIMPLEMENTED();
- return NULL;
+ Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
+ int stack_parameter_count, CallDescriptor::Flags flags,
+ Operator::Properties properties, MachineType return_type,
+ size_t return_count) {
+ const int register_parameter_count = descriptor.GetRegisterParameterCount();
+ const int js_parameter_count =
+ register_parameter_count + stack_parameter_count;
+ const int context_count = 1;
+ const size_t parameter_count =
+ static_cast<size_t>(js_parameter_count + context_count);
+
+ LocationSignature::Builder locations(zone, return_count, parameter_count);
+ MachineSignature::Builder types(zone, return_count, parameter_count);
+
+ // Add returns.
+ if (locations.return_count_ > 0) {
+ locations.AddReturn(regloc(kReturnRegister0));
+ }
+ if (locations.return_count_ > 1) {
+ locations.AddReturn(regloc(kReturnRegister1));
+ }
+ for (size_t i = 0; i < return_count; i++) {
+ types.AddReturn(return_type);
+ }
+
+ // Add parameters in registers and on the stack.
+ for (int i = 0; i < js_parameter_count; i++) {
+ if (i < register_parameter_count) {
+ // The first parameters go in registers.
+ Register reg = descriptor.GetRegisterParameter(i);
+ Representation rep =
+ RepresentationFromType(descriptor.GetParameterType(i));
+ locations.AddParam(regloc(reg));
+ types.AddParam(reptyp(rep));
+ } else {
+ // The rest of the parameters go on the stack.
+ int stack_slot = i - register_parameter_count - stack_parameter_count;
+ locations.AddParam(LinkageLocation::ForCallerFrameSlot(stack_slot));
+ types.AddParam(MachineType::AnyTagged());
+ }
+ }
+ // Add context.
+ locations.AddParam(regloc(kContextRegister));
+ types.AddParam(MachineType::AnyTagged());
+
+ // The target for stub calls is a code object.
+ MachineType target_type = MachineType::AnyTagged();
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallCodeObject, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ types.Build(), // machine_sig
+ locations.Build(), // location_sig
+ stack_parameter_count, // stack_parameter_count
+ properties, // properties
+ kNoCalleeSaved, // callee-saved registers
+ kNoCalleeSaved, // callee-saved fp
+ flags, // flags
+ descriptor.DebugName(isolate));
}
-CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
- MachineSignature* sig) {
- UNIMPLEMENTED();
- return NULL;
+LinkageLocation Linkage::GetOsrValueLocation(int index) const {
+ CHECK(incoming_->IsJSFunctionCall());
+ int parameter_count = static_cast<int>(incoming_->JSParameterCount() - 1);
+ int first_stack_slot = OsrHelper::FirstStackSlotIndex(parameter_count);
+
+ if (index == kOsrContextSpillSlotIndex) {
+ // Context. Use the parameter location of the context spill slot.
+ // Parameter (arity + 2) is special for the context of the function frame.
+ // >> context_index = target + receiver + params + new_target + #args
+ int context_index = 1 + 1 + parameter_count + 1 + 1;
+ return incoming_->GetInputLocation(context_index);
+ } else if (index >= first_stack_slot) {
+ // Local variable stored in this (callee) stack.
+ int spill_index =
+ index - first_stack_slot + StandardFrameConstants::kFixedSlotCount;
+ return LinkageLocation::ForCalleeFrameSlot(spill_index);
+ } else {
+ // Parameter. Use the assigned location from the incoming call descriptor.
+ int parameter_index = 1 + index; // skip index 0, which is the target.
+ return incoming_->GetInputLocation(parameter_index);
+ }
}
-#endif // !V8_TURBOFAN_BACKEND
+
+
+bool Linkage::ParameterHasSecondaryLocation(int index) const {
+ if (incoming_->kind() != CallDescriptor::kCallJSFunction) return false;
+ LinkageLocation loc = GetParameterLocation(index);
+ return (loc == regloc(kJSFunctionRegister) ||
+ loc == regloc(kContextRegister));
}
+
+LinkageLocation Linkage::GetParameterSecondaryLocation(int index) const {
+ DCHECK(ParameterHasSecondaryLocation(index));
+ LinkageLocation loc = GetParameterLocation(index);
+
+ if (loc == regloc(kJSFunctionRegister)) {
+ return LinkageLocation::ForCalleeFrameSlot(Frame::kJSFunctionSlot);
+ } else {
+ DCHECK(loc == regloc(kContextRegister));
+ return LinkageLocation::ForCalleeFrameSlot(Frame::kContextSlot);
+ }
}
-} // namespace v8::internal::compiler
+
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8