| Index: src/compiler/linkage.cc
 | 
| diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc
 | 
| index 5421f4110f0645b2ffadd0b6f350910fc49b9f46..c2973b1045a67c7e0411749a48ef6ef057ca1783 100644
 | 
| --- a/src/compiler/linkage.cc
 | 
| +++ b/src/compiler/linkage.cc
 | 
| @@ -7,6 +7,7 @@
 | 
|  #include "src/compiler/common-operator.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"
 | 
|  
 | 
| @@ -14,6 +15,41 @@ namespace v8 {
 | 
|  namespace internal {
 | 
|  namespace compiler {
 | 
|  
 | 
| +namespace {
 | 
| +LinkageLocation regloc(Register reg) {
 | 
| +  return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +MachineType reptyp(Representation representation) {
 | 
| +  switch (representation.kind()) {
 | 
| +    case Representation::kInteger8:
 | 
| +      return kMachInt8;
 | 
| +    case Representation::kUInteger8:
 | 
| +      return kMachUint8;
 | 
| +    case Representation::kInteger16:
 | 
| +      return kMachInt16;
 | 
| +    case Representation::kUInteger16:
 | 
| +      return kMachUint16;
 | 
| +    case Representation::kInteger32:
 | 
| +      return kMachInt32;
 | 
| +    case Representation::kSmi:
 | 
| +    case Representation::kTagged:
 | 
| +    case Representation::kHeapObject:
 | 
| +      return kMachAnyTagged;
 | 
| +    case Representation::kDouble:
 | 
| +      return kMachFloat64;
 | 
| +    case Representation::kExternal:
 | 
| +      return kMachPtr;
 | 
| +    case Representation::kNone:
 | 
| +    case Representation::kNumRepresentations:
 | 
| +      break;
 | 
| +  }
 | 
| +  UNREACHABLE();
 | 
| +  return kMachNone;
 | 
| +}
 | 
| +}  // namespace
 | 
| +
 | 
|  
 | 
|  std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) {
 | 
|    switch (k) {
 | 
| @@ -247,42 +283,231 @@ bool CallDescriptor::UsesOnlyRegisters() const {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -//==============================================================================
 | 
| -// Provide unimplemented methods on unsupported architectures, to at least link.
 | 
| -//==============================================================================
 | 
| -#if !V8_TURBOFAN_BACKEND
 | 
| +CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 | 
| +    Zone* zone, Runtime::FunctionId function_id, int js_parameter_count,
 | 
| +    Operator::Properties properties) {
 | 
| +  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(kMachAnyTagged);
 | 
| +  }
 | 
| +
 | 
| +  // 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(kMachAnyTagged);
 | 
| +  }
 | 
| +  // Add runtime function itself.
 | 
| +  locations.AddParam(regloc(kRuntimeCallFunctionRegister));
 | 
| +  types.AddParam(kMachAnyTagged);
 | 
| +
 | 
| +  // Add runtime call argument count.
 | 
| +  locations.AddParam(regloc(kRuntimeCallArgCountRegister));
 | 
| +  types.AddParam(kMachPtr);
 | 
| +
 | 
| +  // Add context.
 | 
| +  locations.AddParam(regloc(kContextRegister));
 | 
| +  types.AddParam(kMachAnyTagged);
 | 
| +
 | 
| +  CallDescriptor::Flags flags = Linkage::FrameStateInputCount(function_id) > 0
 | 
| +                                    ? CallDescriptor::kNeedsFrameState
 | 
| +                                    : CallDescriptor::kNoFlags;
 | 
| +
 | 
| +  // The target for runtime calls is a code object.
 | 
| +  MachineType target_type = kMachAnyTagged;
 | 
| +  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::GetJSCallDescriptor(Zone* zone, bool is_osr,
 | 
| -                                             int parameter_count,
 | 
| +                                             int js_parameter_count,
 | 
|                                               CallDescriptor::Flags flags) {
 | 
| -  UNIMPLEMENTED();
 | 
| -  return NULL;
 | 
| -}
 | 
| +  const size_t return_count = 1;
 | 
| +  const size_t context_count = 1;
 | 
| +  const size_t parameter_count = js_parameter_count + context_count;
 | 
|  
 | 
| +  LocationSignature::Builder locations(zone, return_count, parameter_count);
 | 
| +  MachineSignature::Builder types(zone, return_count, parameter_count);
 | 
|  
 | 
| -LinkageLocation Linkage::GetOsrValueLocation(int index) const {
 | 
| -  UNIMPLEMENTED();
 | 
| -  return LinkageLocation(-1);  // Dummy value
 | 
| +  // All JS calls have exactly one return value.
 | 
| +  locations.AddReturn(regloc(kReturnRegister0));
 | 
| +  types.AddReturn(kMachAnyTagged);
 | 
| +
 | 
| +  // 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(kMachAnyTagged);
 | 
| +  }
 | 
| +  // Add context.
 | 
| +  locations.AddParam(regloc(kContextRegister));
 | 
| +  types.AddParam(kMachAnyTagged);
 | 
| +
 | 
| +  // The target for JS function calls is the JSFunction object.
 | 
| +  MachineType target_type = kMachAnyTagged;
 | 
| +  // 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
 | 
| +      flags,                            // flags
 | 
| +      "js-call");
 | 
|  }
 | 
|  
 | 
|  
 | 
| -CallDescriptor* Linkage::GetRuntimeCallDescriptor(
 | 
| -    Zone* zone, Runtime::FunctionId function, int parameter_count,
 | 
| -    Operator::Properties properties) {
 | 
| -  UNIMPLEMENTED();
 | 
| -  return NULL;
 | 
| +CallDescriptor* Linkage::GetInterpreterDispatchDescriptor(Zone* zone) {
 | 
| +  MachineSignature::Builder types(zone, 0, 3);
 | 
| +  LocationSignature::Builder locations(zone, 0, 3);
 | 
| +
 | 
| +  // Add registers for fixed parameters passed via interpreter dispatch.
 | 
| +  STATIC_ASSERT(0 == Linkage::kInterpreterBytecodeOffsetParameter);
 | 
| +  types.AddParam(kMachIntPtr);
 | 
| +  locations.AddParam(regloc(kInterpreterBytecodeOffsetRegister));
 | 
| +
 | 
| +  STATIC_ASSERT(1 == Linkage::kInterpreterBytecodeArrayParameter);
 | 
| +  types.AddParam(kMachAnyTagged);
 | 
| +  locations.AddParam(regloc(kInterpreterBytecodeArrayRegister));
 | 
| +
 | 
| +  STATIC_ASSERT(2 == Linkage::kInterpreterDispatchTableParameter);
 | 
| +  types.AddParam(kMachPtr);
 | 
| +  locations.AddParam(regloc(kInterpreterDispatchTableRegister));
 | 
| +
 | 
| +  LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
 | 
| +  return new (zone) CallDescriptor(          // --
 | 
| +      CallDescriptor::kInterpreterDispatch,  // kind
 | 
| +      kMachNone,                             // 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
 | 
| +      "interpreter-dispatch");
 | 
|  }
 | 
|  
 | 
|  
 | 
| +// TODO(all): Add support for return representations/locations to
 | 
| +// CallInterfaceDescriptor.
 | 
| +// TODO(turbofan): cache call descriptors for code stub calls.
 | 
|  CallDescriptor* Linkage::GetStubCallDescriptor(
 | 
|      Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
 | 
|      int stack_parameter_count, CallDescriptor::Flags flags,
 | 
|      Operator::Properties properties, MachineType return_type) {
 | 
| -  UNIMPLEMENTED();
 | 
| -  return NULL;
 | 
| +  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 return_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 return location.
 | 
| +  locations.AddReturn(regloc(kReturnRegister0));
 | 
| +  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(kMachAnyTagged);
 | 
| +    }
 | 
| +  }
 | 
| +  // Add context.
 | 
| +  locations.AddParam(regloc(kContextRegister));
 | 
| +  types.AddParam(kMachAnyTagged);
 | 
| +
 | 
| +  // The target for stub calls is a code object.
 | 
| +  MachineType target_type = kMachAnyTagged;
 | 
| +  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));
 | 
|  }
 | 
|  
 | 
|  
 | 
| -#endif  // !V8_TURBOFAN_BACKEND
 | 
| +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 + 1) is special for the context of the function frame.
 | 
| +    int context_index = 1 + 1 + parameter_count;  // target + receiver + params
 | 
| +    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;
 | 
| +    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);
 | 
| +  }
 | 
| +}
 | 
|  }  // namespace compiler
 | 
|  }  // namespace internal
 | 
|  }  // namespace v8
 | 
| 
 |