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/code-factory.h"
6 
7 #include "src/bootstrapper.h"
8 #include "src/builtins/builtins-descriptors.h"
9 #include "src/ic/ic.h"
10 #include "src/objects-inl.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 namespace {
16 
17 // TODO(ishell): make it (const Stub& stub) once CodeStub::GetCode() is const.
18 template <typename Stub>
make_callable(Stub & stub)19 Callable make_callable(Stub& stub) {
20   typedef typename Stub::Descriptor Descriptor;
21   return Callable(stub.GetCode(), Descriptor(stub.isolate()));
22 }
23 
24 }  // namespace
25 
26 // static
RuntimeCEntry(Isolate * isolate,int result_size)27 Handle<Code> CodeFactory::RuntimeCEntry(Isolate* isolate, int result_size) {
28   return CodeFactory::CEntry(isolate, result_size);
29 }
30 
31 #define CENTRY_CODE(RS, SD, AM, BE) \
32   BUILTIN_CODE(isolate, CEntry_##RS##_##SD##_##AM##_##BE)
33 
34 // static
CEntry(Isolate * isolate,int result_size,SaveFPRegsMode save_doubles,ArgvMode argv_mode,bool builtin_exit_frame)35 Handle<Code> CodeFactory::CEntry(Isolate* isolate, int result_size,
36                                  SaveFPRegsMode save_doubles,
37                                  ArgvMode argv_mode, bool builtin_exit_frame) {
38   // Aliases for readability below.
39   const int rs = result_size;
40   const SaveFPRegsMode sd = save_doubles;
41   const ArgvMode am = argv_mode;
42   const bool be = builtin_exit_frame;
43 
44   if (rs == 1 && sd == kDontSaveFPRegs && am == kArgvOnStack && !be) {
45     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
46   } else if (rs == 1 && sd == kDontSaveFPRegs && am == kArgvOnStack && be) {
47     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
48   } else if (rs == 1 && sd == kDontSaveFPRegs && am == kArgvInRegister && !be) {
49     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
50   } else if (rs == 1 && sd == kSaveFPRegs && am == kArgvOnStack && !be) {
51     return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
52   } else if (rs == 1 && sd == kSaveFPRegs && am == kArgvOnStack && be) {
53     return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, BuiltinExit);
54   } else if (rs == 2 && sd == kDontSaveFPRegs && am == kArgvOnStack && !be) {
55     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
56   } else if (rs == 2 && sd == kDontSaveFPRegs && am == kArgvOnStack && be) {
57     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
58   } else if (rs == 2 && sd == kDontSaveFPRegs && am == kArgvInRegister && !be) {
59     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
60   } else if (rs == 2 && sd == kSaveFPRegs && am == kArgvOnStack && !be) {
61     return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
62   } else if (rs == 2 && sd == kSaveFPRegs && am == kArgvOnStack && be) {
63     return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, BuiltinExit);
64   }
65 
66   UNREACHABLE();
67 }
68 
69 #undef CENTRY_CODE
70 
71 // static
ApiGetter(Isolate * isolate)72 Callable CodeFactory::ApiGetter(Isolate* isolate) {
73   CallApiGetterStub stub(isolate);
74   return make_callable(stub);
75 }
76 
77 // static
CallApiCallback(Isolate * isolate,int argc)78 Callable CodeFactory::CallApiCallback(Isolate* isolate, int argc) {
79   CallApiCallbackStub stub(isolate, argc);
80   return make_callable(stub);
81 }
82 
83 // static
LoadGlobalIC(Isolate * isolate,TypeofMode typeof_mode)84 Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
85   return Callable(
86       typeof_mode == NOT_INSIDE_TYPEOF
87           ? BUILTIN_CODE(isolate, LoadGlobalICTrampoline)
88           : BUILTIN_CODE(isolate, LoadGlobalICInsideTypeofTrampoline),
89       LoadGlobalDescriptor(isolate));
90 }
91 
92 // static
LoadGlobalICInOptimizedCode(Isolate * isolate,TypeofMode typeof_mode)93 Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
94                                                   TypeofMode typeof_mode) {
95   return Callable(typeof_mode == NOT_INSIDE_TYPEOF
96                       ? BUILTIN_CODE(isolate, LoadGlobalIC)
97                       : BUILTIN_CODE(isolate, LoadGlobalICInsideTypeof),
98                   LoadGlobalWithVectorDescriptor(isolate));
99 }
100 
StoreOwnIC(Isolate * isolate)101 Callable CodeFactory::StoreOwnIC(Isolate* isolate) {
102   // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
103   // already exist in the boilerplate therefore we can use StoreIC.
104   return Callable(BUILTIN_CODE(isolate, StoreICTrampoline),
105                   StoreDescriptor(isolate));
106 }
107 
StoreOwnICInOptimizedCode(Isolate * isolate)108 Callable CodeFactory::StoreOwnICInOptimizedCode(Isolate* isolate) {
109   // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
110   // already exist in the boilerplate therefore we can use StoreIC.
111   return Callable(BUILTIN_CODE(isolate, StoreIC),
112                   StoreWithVectorDescriptor(isolate));
113 }
114 
115 // static
BinaryOperation(Isolate * isolate,Operation op)116 Callable CodeFactory::BinaryOperation(Isolate* isolate, Operation op) {
117   switch (op) {
118     case Operation::kShiftRight:
119       return Builtins::CallableFor(isolate, Builtins::kShiftRight);
120     case Operation::kShiftLeft:
121       return Builtins::CallableFor(isolate, Builtins::kShiftLeft);
122     case Operation::kShiftRightLogical:
123       return Builtins::CallableFor(isolate, Builtins::kShiftRightLogical);
124     case Operation::kAdd:
125       return Builtins::CallableFor(isolate, Builtins::kAdd);
126     case Operation::kSubtract:
127       return Builtins::CallableFor(isolate, Builtins::kSubtract);
128     case Operation::kMultiply:
129       return Builtins::CallableFor(isolate, Builtins::kMultiply);
130     case Operation::kDivide:
131       return Builtins::CallableFor(isolate, Builtins::kDivide);
132     case Operation::kModulus:
133       return Builtins::CallableFor(isolate, Builtins::kModulus);
134     case Operation::kBitwiseOr:
135       return Builtins::CallableFor(isolate, Builtins::kBitwiseOr);
136     case Operation::kBitwiseAnd:
137       return Builtins::CallableFor(isolate, Builtins::kBitwiseAnd);
138     case Operation::kBitwiseXor:
139       return Builtins::CallableFor(isolate, Builtins::kBitwiseXor);
140     default:
141       break;
142   }
143   UNREACHABLE();
144 }
145 
146 // static
NonPrimitiveToPrimitive(Isolate * isolate,ToPrimitiveHint hint)147 Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
148                                               ToPrimitiveHint hint) {
149   return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
150                   TypeConversionDescriptor(isolate));
151 }
152 
153 // static
OrdinaryToPrimitive(Isolate * isolate,OrdinaryToPrimitiveHint hint)154 Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
155                                           OrdinaryToPrimitiveHint hint) {
156   return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
157                   TypeConversionDescriptor(isolate));
158 }
159 
160 // static
StringAdd(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)161 Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
162                                 PretenureFlag pretenure_flag) {
163   if (pretenure_flag == NOT_TENURED) {
164     switch (flags) {
165       case STRING_ADD_CHECK_NONE:
166         return Builtins::CallableFor(isolate,
167                                      Builtins::kStringAdd_CheckNone_NotTenured);
168       case STRING_ADD_CONVERT_LEFT:
169         return Builtins::CallableFor(
170             isolate, Builtins::kStringAdd_ConvertLeft_NotTenured);
171       case STRING_ADD_CONVERT_RIGHT:
172         return Builtins::CallableFor(
173             isolate, Builtins::kStringAdd_ConvertRight_NotTenured);
174     }
175   } else {
176     CHECK_EQ(TENURED, pretenure_flag);
177     CHECK_EQ(STRING_ADD_CHECK_NONE, flags);
178     return Builtins::CallableFor(isolate,
179                                  Builtins::kStringAdd_CheckNone_Tenured);
180   }
181 
182   UNREACHABLE();
183 }
184 
185 // static
ResumeGenerator(Isolate * isolate)186 Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
187   return Callable(BUILTIN_CODE(isolate, ResumeGeneratorTrampoline),
188                   ResumeGeneratorDescriptor(isolate));
189 }
190 
191 // static
FrameDropperTrampoline(Isolate * isolate)192 Callable CodeFactory::FrameDropperTrampoline(Isolate* isolate) {
193   return Callable(BUILTIN_CODE(isolate, FrameDropperTrampoline),
194                   FrameDropperTrampolineDescriptor(isolate));
195 }
196 
197 // static
HandleDebuggerStatement(Isolate * isolate)198 Callable CodeFactory::HandleDebuggerStatement(Isolate* isolate) {
199   return Callable(BUILTIN_CODE(isolate, HandleDebuggerStatement),
200                   ContextOnlyDescriptor(isolate));
201 }
202 
203 // static
FastNewFunctionContext(Isolate * isolate,ScopeType scope_type)204 Callable CodeFactory::FastNewFunctionContext(Isolate* isolate,
205                                              ScopeType scope_type) {
206   return Callable(isolate->builtins()->NewFunctionContext(scope_type),
207                   FastNewFunctionContextDescriptor(isolate));
208 }
209 
210 // static
ArgumentAdaptor(Isolate * isolate)211 Callable CodeFactory::ArgumentAdaptor(Isolate* isolate) {
212   return Callable(BUILTIN_CODE(isolate, ArgumentsAdaptorTrampoline),
213                   ArgumentAdaptorDescriptor(isolate));
214 }
215 
216 // static
Call(Isolate * isolate,ConvertReceiverMode mode)217 Callable CodeFactory::Call(Isolate* isolate, ConvertReceiverMode mode) {
218   return Callable(isolate->builtins()->Call(mode),
219                   CallTrampolineDescriptor(isolate));
220 }
221 
222 // static
CallWithArrayLike(Isolate * isolate)223 Callable CodeFactory::CallWithArrayLike(Isolate* isolate) {
224   return Callable(BUILTIN_CODE(isolate, CallWithArrayLike),
225                   CallWithArrayLikeDescriptor(isolate));
226 }
227 
228 // static
CallWithSpread(Isolate * isolate)229 Callable CodeFactory::CallWithSpread(Isolate* isolate) {
230   return Callable(BUILTIN_CODE(isolate, CallWithSpread),
231                   CallWithSpreadDescriptor(isolate));
232 }
233 
234 // static
CallFunction(Isolate * isolate,ConvertReceiverMode mode)235 Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode) {
236   return Callable(isolate->builtins()->CallFunction(mode),
237                   CallTrampolineDescriptor(isolate));
238 }
239 
240 // static
CallVarargs(Isolate * isolate)241 Callable CodeFactory::CallVarargs(Isolate* isolate) {
242   return Callable(BUILTIN_CODE(isolate, CallVarargs),
243                   CallVarargsDescriptor(isolate));
244 }
245 
246 // static
CallForwardVarargs(Isolate * isolate)247 Callable CodeFactory::CallForwardVarargs(Isolate* isolate) {
248   return Callable(BUILTIN_CODE(isolate, CallForwardVarargs),
249                   CallForwardVarargsDescriptor(isolate));
250 }
251 
252 // static
CallFunctionForwardVarargs(Isolate * isolate)253 Callable CodeFactory::CallFunctionForwardVarargs(Isolate* isolate) {
254   return Callable(BUILTIN_CODE(isolate, CallFunctionForwardVarargs),
255                   CallForwardVarargsDescriptor(isolate));
256 }
257 
258 // static
Construct(Isolate * isolate)259 Callable CodeFactory::Construct(Isolate* isolate) {
260   return Callable(BUILTIN_CODE(isolate, Construct),
261                   ConstructTrampolineDescriptor(isolate));
262 }
263 
264 // static
ConstructWithSpread(Isolate * isolate)265 Callable CodeFactory::ConstructWithSpread(Isolate* isolate) {
266   return Callable(BUILTIN_CODE(isolate, ConstructWithSpread),
267                   ConstructWithSpreadDescriptor(isolate));
268 }
269 
270 // static
ConstructFunction(Isolate * isolate)271 Callable CodeFactory::ConstructFunction(Isolate* isolate) {
272   return Callable(BUILTIN_CODE(isolate, ConstructFunction),
273                   ConstructTrampolineDescriptor(isolate));
274 }
275 
276 // static
ConstructVarargs(Isolate * isolate)277 Callable CodeFactory::ConstructVarargs(Isolate* isolate) {
278   return Callable(BUILTIN_CODE(isolate, ConstructVarargs),
279                   ConstructVarargsDescriptor(isolate));
280 }
281 
282 // static
ConstructForwardVarargs(Isolate * isolate)283 Callable CodeFactory::ConstructForwardVarargs(Isolate* isolate) {
284   return Callable(BUILTIN_CODE(isolate, ConstructForwardVarargs),
285                   ConstructForwardVarargsDescriptor(isolate));
286 }
287 
288 // static
ConstructFunctionForwardVarargs(Isolate * isolate)289 Callable CodeFactory::ConstructFunctionForwardVarargs(Isolate* isolate) {
290   return Callable(BUILTIN_CODE(isolate, ConstructFunctionForwardVarargs),
291                   ConstructForwardVarargsDescriptor(isolate));
292 }
293 
294 // static
InterpreterPushArgsThenCall(Isolate * isolate,ConvertReceiverMode receiver_mode,InterpreterPushArgsMode mode)295 Callable CodeFactory::InterpreterPushArgsThenCall(
296     Isolate* isolate, ConvertReceiverMode receiver_mode,
297     InterpreterPushArgsMode mode) {
298   return Callable(
299       isolate->builtins()->InterpreterPushArgsThenCall(receiver_mode, mode),
300       InterpreterPushArgsThenCallDescriptor(isolate));
301 }
302 
303 // static
InterpreterPushArgsThenConstruct(Isolate * isolate,InterpreterPushArgsMode mode)304 Callable CodeFactory::InterpreterPushArgsThenConstruct(
305     Isolate* isolate, InterpreterPushArgsMode mode) {
306   return Callable(isolate->builtins()->InterpreterPushArgsThenConstruct(mode),
307                   InterpreterPushArgsThenConstructDescriptor(isolate));
308 }
309 
310 // static
InterpreterCEntry(Isolate * isolate,int result_size)311 Callable CodeFactory::InterpreterCEntry(Isolate* isolate, int result_size) {
312   // Note: If we ever use fpregs in the interpreter then we will need to
313   // save fpregs too.
314   Handle<Code> code = CodeFactory::CEntry(isolate, result_size, kDontSaveFPRegs,
315                                           kArgvInRegister);
316   return Callable(code, InterpreterCEntryDescriptor(isolate));
317 }
318 
319 // static
InterpreterOnStackReplacement(Isolate * isolate)320 Callable CodeFactory::InterpreterOnStackReplacement(Isolate* isolate) {
321   return Callable(BUILTIN_CODE(isolate, InterpreterOnStackReplacement),
322                   ContextOnlyDescriptor(isolate));
323 }
324 
325 // static
ArrayConstructor(Isolate * isolate)326 Callable CodeFactory::ArrayConstructor(Isolate* isolate) {
327   ArrayConstructorStub stub(isolate);
328   return make_callable(stub);
329 }
330 
331 // static
ArrayPop(Isolate * isolate)332 Callable CodeFactory::ArrayPop(Isolate* isolate) {
333   return Callable(BUILTIN_CODE(isolate, ArrayPop), BuiltinDescriptor(isolate));
334 }
335 
336 // static
ArrayShift(Isolate * isolate)337 Callable CodeFactory::ArrayShift(Isolate* isolate) {
338   return Callable(BUILTIN_CODE(isolate, ArrayShift),
339                   BuiltinDescriptor(isolate));
340 }
341 
342 // static
ExtractFastJSArray(Isolate * isolate)343 Callable CodeFactory::ExtractFastJSArray(Isolate* isolate) {
344   return Callable(BUILTIN_CODE(isolate, ExtractFastJSArray),
345                   ExtractFastJSArrayDescriptor(isolate));
346 }
347 
348 // static
CloneFastJSArray(Isolate * isolate)349 Callable CodeFactory::CloneFastJSArray(Isolate* isolate) {
350   return Callable(BUILTIN_CODE(isolate, CloneFastJSArray),
351                   CloneFastJSArrayDescriptor(isolate));
352 }
353 
354 // static
ArrayPush(Isolate * isolate)355 Callable CodeFactory::ArrayPush(Isolate* isolate) {
356   return Callable(BUILTIN_CODE(isolate, ArrayPush), BuiltinDescriptor(isolate));
357 }
358 
359 // static
FunctionPrototypeBind(Isolate * isolate)360 Callable CodeFactory::FunctionPrototypeBind(Isolate* isolate) {
361   return Callable(BUILTIN_CODE(isolate, FunctionPrototypeBind),
362                   BuiltinDescriptor(isolate));
363 }
364 
365 // static
TransitionElementsKind(Isolate * isolate,ElementsKind from,ElementsKind to,bool is_jsarray)366 Callable CodeFactory::TransitionElementsKind(Isolate* isolate,
367                                              ElementsKind from, ElementsKind to,
368                                              bool is_jsarray) {
369   TransitionElementsKindStub stub(isolate, from, to, is_jsarray);
370   return make_callable(stub);
371 }
372 
373 }  // namespace internal
374 }  // namespace v8
375