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/ic/ic.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 namespace {
14 
15 // TODO(ishell): make it (const Stub& stub) once CodeStub::GetCode() is const.
16 template <typename Stub>
make_callable(Stub & stub)17 Callable make_callable(Stub& stub) {
18   typedef typename Stub::Descriptor Descriptor;
19   return Callable(stub.GetCode(), Descriptor(stub.isolate()));
20 }
21 
22 }  // namespace
23 
24 // static
LoadIC(Isolate * isolate)25 Callable CodeFactory::LoadIC(Isolate* isolate) {
26   LoadICTrampolineStub stub(isolate);
27   return make_callable(stub);
28 }
29 
30 // static
ApiGetter(Isolate * isolate)31 Callable CodeFactory::ApiGetter(Isolate* isolate) {
32   CallApiGetterStub stub(isolate);
33   return make_callable(stub);
34 }
35 
36 // static
LoadICInOptimizedCode(Isolate * isolate)37 Callable CodeFactory::LoadICInOptimizedCode(Isolate* isolate) {
38   LoadICStub stub(isolate);
39   return make_callable(stub);
40 }
41 
42 // static
LoadGlobalIC(Isolate * isolate,TypeofMode typeof_mode)43 Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
44   LoadGlobalICTrampolineStub stub(isolate, LoadGlobalICState(typeof_mode));
45   return make_callable(stub);
46 }
47 
48 // static
LoadGlobalICInOptimizedCode(Isolate * isolate,TypeofMode typeof_mode)49 Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
50                                                   TypeofMode typeof_mode) {
51   LoadGlobalICStub stub(isolate, LoadGlobalICState(typeof_mode));
52   return make_callable(stub);
53 }
54 
55 // static
KeyedLoadIC(Isolate * isolate)56 Callable CodeFactory::KeyedLoadIC(Isolate* isolate) {
57   KeyedLoadICTrampolineTFStub stub(isolate);
58   return make_callable(stub);
59 }
60 
61 // static
KeyedLoadICInOptimizedCode(Isolate * isolate)62 Callable CodeFactory::KeyedLoadICInOptimizedCode(Isolate* isolate) {
63   KeyedLoadICTFStub stub(isolate);
64   return make_callable(stub);
65 }
66 
67 // static
KeyedLoadIC_Megamorphic(Isolate * isolate)68 Callable CodeFactory::KeyedLoadIC_Megamorphic(Isolate* isolate) {
69   return Callable(isolate->builtins()->KeyedLoadIC_Megamorphic_TF(),
70                   LoadWithVectorDescriptor(isolate));
71 }
72 
73 // static
CallIC(Isolate * isolate,ConvertReceiverMode mode,TailCallMode tail_call_mode)74 Callable CodeFactory::CallIC(Isolate* isolate, ConvertReceiverMode mode,
75                              TailCallMode tail_call_mode) {
76   CallICTrampolineStub stub(isolate, CallICState(mode, tail_call_mode));
77   return make_callable(stub);
78 }
79 
80 // static
CallICInOptimizedCode(Isolate * isolate,ConvertReceiverMode mode,TailCallMode tail_call_mode)81 Callable CodeFactory::CallICInOptimizedCode(Isolate* isolate,
82                                             ConvertReceiverMode mode,
83                                             TailCallMode tail_call_mode) {
84   CallICStub stub(isolate, CallICState(mode, tail_call_mode));
85   return make_callable(stub);
86 }
87 
88 // static
StoreIC(Isolate * isolate,LanguageMode language_mode)89 Callable CodeFactory::StoreIC(Isolate* isolate, LanguageMode language_mode) {
90   StoreICTrampolineStub stub(isolate, StoreICState(language_mode));
91   return make_callable(stub);
92 }
93 
94 // static
StoreICInOptimizedCode(Isolate * isolate,LanguageMode language_mode)95 Callable CodeFactory::StoreICInOptimizedCode(Isolate* isolate,
96                                              LanguageMode language_mode) {
97   StoreICStub stub(isolate, StoreICState(language_mode));
98   return make_callable(stub);
99 }
100 
101 // static
KeyedStoreIC(Isolate * isolate,LanguageMode language_mode)102 Callable CodeFactory::KeyedStoreIC(Isolate* isolate,
103                                    LanguageMode language_mode) {
104   if (FLAG_tf_store_ic_stub) {
105     KeyedStoreICTrampolineTFStub stub(isolate, StoreICState(language_mode));
106     return make_callable(stub);
107   }
108   KeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
109   return make_callable(stub);
110 }
111 
112 // static
KeyedStoreICInOptimizedCode(Isolate * isolate,LanguageMode language_mode)113 Callable CodeFactory::KeyedStoreICInOptimizedCode(Isolate* isolate,
114                                                   LanguageMode language_mode) {
115   if (FLAG_tf_store_ic_stub) {
116     KeyedStoreICTFStub stub(isolate, StoreICState(language_mode));
117     return make_callable(stub);
118   }
119   KeyedStoreICStub stub(isolate, StoreICState(language_mode));
120   return make_callable(stub);
121 }
122 
123 // static
KeyedStoreIC_Megamorphic(Isolate * isolate,LanguageMode language_mode)124 Callable CodeFactory::KeyedStoreIC_Megamorphic(Isolate* isolate,
125                                                LanguageMode language_mode) {
126   if (FLAG_tf_store_ic_stub) {
127     return Callable(
128         language_mode == STRICT
129             ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict_TF()
130             : isolate->builtins()->KeyedStoreIC_Megamorphic_TF(),
131         StoreWithVectorDescriptor(isolate));
132   }
133   return Callable(language_mode == STRICT
134                       ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
135                       : isolate->builtins()->KeyedStoreIC_Megamorphic(),
136                   StoreWithVectorDescriptor(isolate));
137 }
138 
139 // static
CompareIC(Isolate * isolate,Token::Value op)140 Callable CodeFactory::CompareIC(Isolate* isolate, Token::Value op) {
141   CompareICStub stub(isolate, op);
142   return make_callable(stub);
143 }
144 
145 // static
BinaryOpIC(Isolate * isolate,Token::Value op)146 Callable CodeFactory::BinaryOpIC(Isolate* isolate, Token::Value op) {
147   BinaryOpICStub stub(isolate, op);
148   return make_callable(stub);
149 }
150 
151 // static
GetProperty(Isolate * isolate)152 Callable CodeFactory::GetProperty(Isolate* isolate) {
153   GetPropertyStub stub(isolate);
154   return make_callable(stub);
155 }
156 
157 // static
ToBoolean(Isolate * isolate)158 Callable CodeFactory::ToBoolean(Isolate* isolate) {
159   return Callable(isolate->builtins()->ToBoolean(),
160                   TypeConversionDescriptor(isolate));
161 }
162 
163 // static
ToNumber(Isolate * isolate)164 Callable CodeFactory::ToNumber(Isolate* isolate) {
165   return Callable(isolate->builtins()->ToNumber(),
166                   TypeConversionDescriptor(isolate));
167 }
168 
169 // static
NonNumberToNumber(Isolate * isolate)170 Callable CodeFactory::NonNumberToNumber(Isolate* isolate) {
171   return Callable(isolate->builtins()->NonNumberToNumber(),
172                   TypeConversionDescriptor(isolate));
173 }
174 
175 // static
StringToNumber(Isolate * isolate)176 Callable CodeFactory::StringToNumber(Isolate* isolate) {
177   return Callable(isolate->builtins()->StringToNumber(),
178                   TypeConversionDescriptor(isolate));
179 }
180 
181 // static
ToName(Isolate * isolate)182 Callable CodeFactory::ToName(Isolate* isolate) {
183   return Callable(isolate->builtins()->ToName(),
184                   TypeConversionDescriptor(isolate));
185 }
186 
187 // static
NonPrimitiveToPrimitive(Isolate * isolate,ToPrimitiveHint hint)188 Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
189                                               ToPrimitiveHint hint) {
190   return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
191                   TypeConversionDescriptor(isolate));
192 }
193 
194 // static
OrdinaryToPrimitive(Isolate * isolate,OrdinaryToPrimitiveHint hint)195 Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
196                                           OrdinaryToPrimitiveHint hint) {
197   return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
198                   TypeConversionDescriptor(isolate));
199 }
200 
201 // static
NumberToString(Isolate * isolate)202 Callable CodeFactory::NumberToString(Isolate* isolate) {
203   NumberToStringStub stub(isolate);
204   return make_callable(stub);
205 }
206 
207 // static
RegExpExec(Isolate * isolate)208 Callable CodeFactory::RegExpExec(Isolate* isolate) {
209   RegExpExecStub stub(isolate);
210   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
211 }
212 
213 // static
StringFromCharCode(Isolate * isolate)214 Callable CodeFactory::StringFromCharCode(Isolate* isolate) {
215   Handle<Code> code(isolate->builtins()->StringFromCharCode());
216   return Callable(code, BuiltinDescriptor(isolate));
217 }
218 
219 #define DECLARE_TFS(Name, Kind, Extra, InterfaceDescriptor) \
220   typedef InterfaceDescriptor##Descriptor Name##Descriptor;
BUILTIN_LIST(IGNORE_BUILTIN,IGNORE_BUILTIN,IGNORE_BUILTIN,DECLARE_TFS,IGNORE_BUILTIN,IGNORE_BUILTIN,IGNORE_BUILTIN)221 BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, DECLARE_TFS,
222              IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
223 #undef DECLARE_TFS
224 
225 #define TFS_BUILTIN(Name)                             \
226   Callable CodeFactory::Name(Isolate* isolate) {      \
227     Handle<Code> code(isolate->builtins()->Name());   \
228     return Callable(code, Name##Descriptor(isolate)); \
229   }
230 
231 TFS_BUILTIN(ToString)
232 TFS_BUILTIN(Add)
233 TFS_BUILTIN(Subtract)
234 TFS_BUILTIN(Multiply)
235 TFS_BUILTIN(Divide)
236 TFS_BUILTIN(Modulus)
237 TFS_BUILTIN(BitwiseAnd)
238 TFS_BUILTIN(BitwiseOr)
239 TFS_BUILTIN(BitwiseXor)
240 TFS_BUILTIN(ShiftLeft)
241 TFS_BUILTIN(ShiftRight)
242 TFS_BUILTIN(ShiftRightLogical)
243 TFS_BUILTIN(LessThan)
244 TFS_BUILTIN(LessThanOrEqual)
245 TFS_BUILTIN(GreaterThan)
246 TFS_BUILTIN(GreaterThanOrEqual)
247 TFS_BUILTIN(Equal)
248 TFS_BUILTIN(NotEqual)
249 TFS_BUILTIN(StrictEqual)
250 TFS_BUILTIN(StrictNotEqual)
251 TFS_BUILTIN(HasProperty)
252 TFS_BUILTIN(ToInteger)
253 TFS_BUILTIN(ToLength)
254 TFS_BUILTIN(ToObject)
255 TFS_BUILTIN(Typeof)
256 TFS_BUILTIN(InstanceOf)
257 TFS_BUILTIN(OrdinaryHasInstance)
258 TFS_BUILTIN(ForInFilter)
259 
260 #undef TFS_BUILTIN
261 
262 // static
263 Callable CodeFactory::Inc(Isolate* isolate) {
264   IncStub stub(isolate);
265   return make_callable(stub);
266 }
267 
268 // static
Dec(Isolate * isolate)269 Callable CodeFactory::Dec(Isolate* isolate) {
270   DecStub stub(isolate);
271   return make_callable(stub);
272 }
273 
274 // static
StringAdd(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)275 Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
276                                 PretenureFlag pretenure_flag) {
277   StringAddStub stub(isolate, flags, pretenure_flag);
278   return make_callable(stub);
279 }
280 
281 // static
StringCompare(Isolate * isolate,Token::Value token)282 Callable CodeFactory::StringCompare(Isolate* isolate, Token::Value token) {
283   switch (token) {
284     case Token::EQ:
285     case Token::EQ_STRICT:
286       return StringEqual(isolate);
287     case Token::NE:
288     case Token::NE_STRICT:
289       return StringNotEqual(isolate);
290     case Token::LT:
291       return StringLessThan(isolate);
292     case Token::GT:
293       return StringGreaterThan(isolate);
294     case Token::LTE:
295       return StringLessThanOrEqual(isolate);
296     case Token::GTE:
297       return StringGreaterThanOrEqual(isolate);
298     default:
299       break;
300   }
301   UNREACHABLE();
302   return StringEqual(isolate);
303 }
304 
305 // static
StringEqual(Isolate * isolate)306 Callable CodeFactory::StringEqual(Isolate* isolate) {
307   return Callable(isolate->builtins()->StringEqual(),
308                   CompareDescriptor(isolate));
309 }
310 
311 // static
StringNotEqual(Isolate * isolate)312 Callable CodeFactory::StringNotEqual(Isolate* isolate) {
313   return Callable(isolate->builtins()->StringNotEqual(),
314                   CompareDescriptor(isolate));
315 }
316 
317 // static
StringLessThan(Isolate * isolate)318 Callable CodeFactory::StringLessThan(Isolate* isolate) {
319   return Callable(isolate->builtins()->StringLessThan(),
320                   CompareDescriptor(isolate));
321 }
322 
323 // static
StringLessThanOrEqual(Isolate * isolate)324 Callable CodeFactory::StringLessThanOrEqual(Isolate* isolate) {
325   return Callable(isolate->builtins()->StringLessThanOrEqual(),
326                   CompareDescriptor(isolate));
327 }
328 
329 // static
StringGreaterThan(Isolate * isolate)330 Callable CodeFactory::StringGreaterThan(Isolate* isolate) {
331   return Callable(isolate->builtins()->StringGreaterThan(),
332                   CompareDescriptor(isolate));
333 }
334 
335 // static
StringGreaterThanOrEqual(Isolate * isolate)336 Callable CodeFactory::StringGreaterThanOrEqual(Isolate* isolate) {
337   return Callable(isolate->builtins()->StringGreaterThanOrEqual(),
338                   CompareDescriptor(isolate));
339 }
340 
341 // static
SubString(Isolate * isolate)342 Callable CodeFactory::SubString(Isolate* isolate) {
343   SubStringStub stub(isolate);
344   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
345 }
346 
347 // static
ResumeGenerator(Isolate * isolate)348 Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
349   return Callable(isolate->builtins()->ResumeGeneratorTrampoline(),
350                   ResumeGeneratorDescriptor(isolate));
351 }
352 
353 // static
FastCloneRegExp(Isolate * isolate)354 Callable CodeFactory::FastCloneRegExp(Isolate* isolate) {
355   FastCloneRegExpStub stub(isolate);
356   return make_callable(stub);
357 }
358 
359 // static
FastCloneShallowArray(Isolate * isolate)360 Callable CodeFactory::FastCloneShallowArray(Isolate* isolate) {
361   // TODO(mstarzinger): Thread through AllocationSiteMode at some point.
362   FastCloneShallowArrayStub stub(isolate, DONT_TRACK_ALLOCATION_SITE);
363   return make_callable(stub);
364 }
365 
366 // static
FastCloneShallowObject(Isolate * isolate,int length)367 Callable CodeFactory::FastCloneShallowObject(Isolate* isolate, int length) {
368   FastCloneShallowObjectStub stub(isolate, length);
369   return make_callable(stub);
370 }
371 
372 
373 // static
FastNewFunctionContext(Isolate * isolate)374 Callable CodeFactory::FastNewFunctionContext(Isolate* isolate) {
375   FastNewFunctionContextStub stub(isolate);
376   return make_callable(stub);
377 }
378 
379 // static
FastNewClosure(Isolate * isolate)380 Callable CodeFactory::FastNewClosure(Isolate* isolate) {
381   FastNewClosureStub stub(isolate);
382   return make_callable(stub);
383 }
384 
385 // static
FastNewObject(Isolate * isolate)386 Callable CodeFactory::FastNewObject(Isolate* isolate) {
387   FastNewObjectStub stub(isolate);
388   return make_callable(stub);
389 }
390 
391 // static
FastNewRestParameter(Isolate * isolate,bool skip_stub_frame)392 Callable CodeFactory::FastNewRestParameter(Isolate* isolate,
393                                            bool skip_stub_frame) {
394   FastNewRestParameterStub stub(isolate, skip_stub_frame);
395   return make_callable(stub);
396 }
397 
398 // static
FastNewSloppyArguments(Isolate * isolate,bool skip_stub_frame)399 Callable CodeFactory::FastNewSloppyArguments(Isolate* isolate,
400                                              bool skip_stub_frame) {
401   FastNewSloppyArgumentsStub stub(isolate, skip_stub_frame);
402   return make_callable(stub);
403 }
404 
405 // static
FastNewStrictArguments(Isolate * isolate,bool skip_stub_frame)406 Callable CodeFactory::FastNewStrictArguments(Isolate* isolate,
407                                              bool skip_stub_frame) {
408   FastNewStrictArgumentsStub stub(isolate, skip_stub_frame);
409   return make_callable(stub);
410 }
411 
412 // static
CopyFastSmiOrObjectElements(Isolate * isolate)413 Callable CodeFactory::CopyFastSmiOrObjectElements(Isolate* isolate) {
414   return Callable(isolate->builtins()->CopyFastSmiOrObjectElements(),
415                   CopyFastSmiOrObjectElementsDescriptor(isolate));
416 }
417 
418 // static
GrowFastDoubleElements(Isolate * isolate)419 Callable CodeFactory::GrowFastDoubleElements(Isolate* isolate) {
420   return Callable(isolate->builtins()->GrowFastDoubleElements(),
421                   GrowArrayElementsDescriptor(isolate));
422 }
423 
424 // static
GrowFastSmiOrObjectElements(Isolate * isolate)425 Callable CodeFactory::GrowFastSmiOrObjectElements(Isolate* isolate) {
426   return Callable(isolate->builtins()->GrowFastSmiOrObjectElements(),
427                   GrowArrayElementsDescriptor(isolate));
428 }
429 
430 // static
AllocateHeapNumber(Isolate * isolate)431 Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) {
432   AllocateHeapNumberStub stub(isolate);
433   return make_callable(stub);
434 }
435 
436 #define SIMD128_ALLOC(TYPE, Type, type, lane_count, lane_type) \
437   Callable CodeFactory::Allocate##Type(Isolate* isolate) {     \
438     Allocate##Type##Stub stub(isolate);                        \
439     return make_callable(stub);                                \
440   }
SIMD128_TYPES(SIMD128_ALLOC)441 SIMD128_TYPES(SIMD128_ALLOC)
442 #undef SIMD128_ALLOC
443 
444 // static
445 Callable CodeFactory::ArgumentAdaptor(Isolate* isolate) {
446   return Callable(isolate->builtins()->ArgumentsAdaptorTrampoline(),
447                   ArgumentAdaptorDescriptor(isolate));
448 }
449 
450 // static
Call(Isolate * isolate,ConvertReceiverMode mode,TailCallMode tail_call_mode)451 Callable CodeFactory::Call(Isolate* isolate, ConvertReceiverMode mode,
452                            TailCallMode tail_call_mode) {
453   return Callable(isolate->builtins()->Call(mode, tail_call_mode),
454                   CallTrampolineDescriptor(isolate));
455 }
456 
457 // static
CallFunction(Isolate * isolate,ConvertReceiverMode mode)458 Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode) {
459   return Callable(isolate->builtins()->CallFunction(mode),
460                   CallTrampolineDescriptor(isolate));
461 }
462 
463 // static
Construct(Isolate * isolate)464 Callable CodeFactory::Construct(Isolate* isolate) {
465   return Callable(isolate->builtins()->Construct(),
466                   ConstructTrampolineDescriptor(isolate));
467 }
468 
469 // static
ConstructFunction(Isolate * isolate)470 Callable CodeFactory::ConstructFunction(Isolate* isolate) {
471   return Callable(isolate->builtins()->ConstructFunction(),
472                   ConstructTrampolineDescriptor(isolate));
473 }
474 
475 // static
InterpreterPushArgsAndCall(Isolate * isolate,TailCallMode tail_call_mode,CallableType function_type)476 Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
477                                                  TailCallMode tail_call_mode,
478                                                  CallableType function_type) {
479   return Callable(isolate->builtins()->InterpreterPushArgsAndCall(
480                       tail_call_mode, function_type),
481                   InterpreterPushArgsAndCallDescriptor(isolate));
482 }
483 
484 // static
InterpreterPushArgsAndConstruct(Isolate * isolate,CallableType function_type)485 Callable CodeFactory::InterpreterPushArgsAndConstruct(
486     Isolate* isolate, CallableType function_type) {
487   return Callable(
488       isolate->builtins()->InterpreterPushArgsAndConstruct(function_type),
489       InterpreterPushArgsAndConstructDescriptor(isolate));
490 }
491 
492 // static
InterpreterPushArgsAndConstructArray(Isolate * isolate)493 Callable CodeFactory::InterpreterPushArgsAndConstructArray(Isolate* isolate) {
494   return Callable(isolate->builtins()->InterpreterPushArgsAndConstructArray(),
495                   InterpreterPushArgsAndConstructArrayDescriptor(isolate));
496 }
497 
498 // static
InterpreterCEntry(Isolate * isolate,int result_size)499 Callable CodeFactory::InterpreterCEntry(Isolate* isolate, int result_size) {
500   // Note: If we ever use fpregs in the interpreter then we will need to
501   // save fpregs too.
502   CEntryStub stub(isolate, result_size, kDontSaveFPRegs, kArgvInRegister);
503   return Callable(stub.GetCode(), InterpreterCEntryDescriptor(isolate));
504 }
505 
506 // static
InterpreterOnStackReplacement(Isolate * isolate)507 Callable CodeFactory::InterpreterOnStackReplacement(Isolate* isolate) {
508   return Callable(isolate->builtins()->InterpreterOnStackReplacement(),
509                   ContextOnlyDescriptor(isolate));
510 }
511 
512 }  // namespace internal
513 }  // namespace v8
514