1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/compiler/linkage.h" 6 7 #include "src/code-stubs.h" 8 #include "src/compiler.h" 9 #include "src/compiler/node.h" 10 #include "src/compiler/pipeline.h" 11 #include "src/scopes.h" 12 13 namespace v8 { 14 namespace internal { 15 namespace compiler { 16 17 18 OStream& operator<<(OStream& os, const CallDescriptor::Kind& k) { 19 switch (k) { 20 case CallDescriptor::kCallCodeObject: 21 os << "Code"; 22 break; 23 case CallDescriptor::kCallJSFunction: 24 os << "JS"; 25 break; 26 case CallDescriptor::kCallAddress: 27 os << "Addr"; 28 break; 29 } 30 return os; 31 } 32 33 34 OStream& operator<<(OStream& os, const CallDescriptor& d) { 35 // TODO(svenpanne) Output properties etc. and be less cryptic. 36 return os << d.kind() << ":" << d.debug_name() << ":r" << d.ReturnCount() 37 << "j" << d.JSParameterCount() << "i" << d.InputCount() << "f" 38 << d.FrameStateCount(); 39 } 40 41 42 Linkage::Linkage(CompilationInfo* info) : info_(info) { 43 if (info->function() != NULL) { 44 // If we already have the function literal, use the number of parameters 45 // plus the receiver. 46 incoming_ = GetJSCallDescriptor(1 + info->function()->parameter_count()); 47 } else if (!info->closure().is_null()) { 48 // If we are compiling a JS function, use a JS call descriptor, 49 // plus the receiver. 50 SharedFunctionInfo* shared = info->closure()->shared(); 51 incoming_ = GetJSCallDescriptor(1 + shared->formal_parameter_count()); 52 } else if (info->code_stub() != NULL) { 53 // Use the code stub interface descriptor. 54 CallInterfaceDescriptor descriptor = 55 info->code_stub()->GetCallInterfaceDescriptor(); 56 incoming_ = GetStubCallDescriptor(descriptor); 57 } else { 58 incoming_ = NULL; // TODO(titzer): ? 59 } 60 } 61 62 63 FrameOffset Linkage::GetFrameOffset(int spill_slot, Frame* frame, int extra) { 64 if (frame->GetSpillSlotCount() > 0 || incoming_->IsJSFunctionCall() || 65 incoming_->kind() == CallDescriptor::kCallAddress) { 66 int offset; 67 int register_save_area_size = frame->GetRegisterSaveAreaSize(); 68 if (spill_slot >= 0) { 69 // Local or spill slot. Skip the frame pointer, function, and 70 // context in the fixed part of the frame. 71 offset = 72 -(spill_slot + 1) * kPointerSize - register_save_area_size + extra; 73 } else { 74 // Incoming parameter. Skip the return address. 75 offset = -(spill_slot + 1) * kPointerSize + kFPOnStackSize + 76 kPCOnStackSize + extra; 77 } 78 return FrameOffset::FromFramePointer(offset); 79 } else { 80 // No frame. Retrieve all parameters relative to stack pointer. 81 DCHECK(spill_slot < 0); // Must be a parameter. 82 int register_save_area_size = frame->GetRegisterSaveAreaSize(); 83 int offset = register_save_area_size - (spill_slot + 1) * kPointerSize + 84 kPCOnStackSize + extra; 85 return FrameOffset::FromStackPointer(offset); 86 } 87 } 88 89 90 CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count) { 91 return GetJSCallDescriptor(parameter_count, this->info_->zone()); 92 } 93 94 95 CallDescriptor* Linkage::GetRuntimeCallDescriptor( 96 Runtime::FunctionId function, int parameter_count, 97 Operator::Properties properties) { 98 return GetRuntimeCallDescriptor(function, parameter_count, properties, 99 this->info_->zone()); 100 } 101 102 103 CallDescriptor* Linkage::GetStubCallDescriptor( 104 CallInterfaceDescriptor descriptor, int stack_parameter_count, 105 CallDescriptor::Flags flags) { 106 return GetStubCallDescriptor(descriptor, stack_parameter_count, flags, 107 this->info_->zone()); 108 } 109 110 111 // static 112 bool Linkage::NeedsFrameState(Runtime::FunctionId function) { 113 if (!FLAG_turbo_deoptimization) { 114 return false; 115 } 116 // TODO(jarin) At the moment, we only add frame state for 117 // few chosen runtime functions. 118 switch (function) { 119 case Runtime::kDebugBreak: 120 case Runtime::kDebugGetLoadedScripts: 121 case Runtime::kDeoptimizeFunction: 122 case Runtime::kInlineCallFunction: 123 case Runtime::kPrepareStep: 124 case Runtime::kSetScriptBreakPoint: 125 case Runtime::kStackGuard: 126 case Runtime::kCheckExecutionState: 127 case Runtime::kDebugEvaluate: 128 case Runtime::kCollectStackTrace: 129 return true; 130 default: 131 return false; 132 } 133 } 134 135 136 //============================================================================== 137 // Provide unimplemented methods on unsupported architectures, to at least link. 138 //============================================================================== 139 #if !V8_TURBOFAN_BACKEND 140 CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) { 141 UNIMPLEMENTED(); 142 return NULL; 143 } 144 145 146 CallDescriptor* Linkage::GetRuntimeCallDescriptor( 147 Runtime::FunctionId function, int parameter_count, 148 Operator::Properties properties, Zone* zone) { 149 UNIMPLEMENTED(); 150 return NULL; 151 } 152 153 154 CallDescriptor* Linkage::GetStubCallDescriptor( 155 CallInterfaceDescriptor descriptor, int stack_parameter_count, 156 CallDescriptor::Flags flags, Zone* zone) { 157 UNIMPLEMENTED(); 158 return NULL; 159 } 160 161 162 CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone, 163 MachineSignature* sig) { 164 UNIMPLEMENTED(); 165 return NULL; 166 } 167 #endif // !V8_TURBOFAN_BACKEND 168 } 169 } 170 } // namespace v8::internal::compiler 171