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