• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/codegen/code-factory.h"
6 
7 #include "src/builtins/builtins-descriptors.h"
8 #include "src/ic/ic.h"
9 #include "src/init/bootstrapper.h"
10 #include "src/objects/allocation-site-inl.h"
11 #include "src/objects/objects-inl.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // static
RuntimeCEntry(Isolate * isolate,int result_size)17 Handle<Code> CodeFactory::RuntimeCEntry(Isolate* isolate, int result_size) {
18   return CodeFactory::CEntry(isolate, result_size);
19 }
20 
21 #define CENTRY_CODE(RS, SD, AM, BE) \
22   BUILTIN_CODE(isolate, CEntry_##RS##_##SD##_##AM##_##BE)
23 
24 // static
CEntry(Isolate * isolate,int result_size,SaveFPRegsMode save_doubles,ArgvMode argv_mode,bool builtin_exit_frame)25 Handle<Code> CodeFactory::CEntry(Isolate* isolate, int result_size,
26                                  SaveFPRegsMode save_doubles,
27                                  ArgvMode argv_mode, bool builtin_exit_frame) {
28   // Aliases for readability below.
29   const int rs = result_size;
30   const SaveFPRegsMode sd = save_doubles;
31   const ArgvMode am = argv_mode;
32   const bool be = builtin_exit_frame;
33 
34   if (rs == 1 && sd == kDontSaveFPRegs && am == kArgvOnStack && !be) {
35     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
36   } else if (rs == 1 && sd == kDontSaveFPRegs && am == kArgvOnStack && be) {
37     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
38   } else if (rs == 1 && sd == kDontSaveFPRegs && am == kArgvInRegister && !be) {
39     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
40   } else if (rs == 1 && sd == kSaveFPRegs && am == kArgvOnStack && !be) {
41     return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
42   } else if (rs == 1 && sd == kSaveFPRegs && am == kArgvOnStack && be) {
43     return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, BuiltinExit);
44   } else if (rs == 2 && sd == kDontSaveFPRegs && am == kArgvOnStack && !be) {
45     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
46   } else if (rs == 2 && sd == kDontSaveFPRegs && am == kArgvOnStack && be) {
47     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
48   } else if (rs == 2 && sd == kDontSaveFPRegs && am == kArgvInRegister && !be) {
49     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
50   } else if (rs == 2 && sd == kSaveFPRegs && am == kArgvOnStack && !be) {
51     return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
52   } else if (rs == 2 && sd == kSaveFPRegs && am == kArgvOnStack && be) {
53     return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, BuiltinExit);
54   }
55 
56   UNREACHABLE();
57 }
58 
59 #undef CENTRY_CODE
60 
61 // static
ApiGetter(Isolate * isolate)62 Callable CodeFactory::ApiGetter(Isolate* isolate) {
63   return Builtins::CallableFor(isolate, Builtins::kCallApiGetter);
64 }
65 
66 // static
CallApiCallback(Isolate * isolate)67 Callable CodeFactory::CallApiCallback(Isolate* isolate) {
68   return Builtins::CallableFor(isolate, Builtins::kCallApiCallback);
69 }
70 
71 // static
LoadGlobalIC(Isolate * isolate,TypeofMode typeof_mode)72 Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
73   return typeof_mode == NOT_INSIDE_TYPEOF
74              ? Builtins::CallableFor(isolate, Builtins::kLoadGlobalICTrampoline)
75              : Builtins::CallableFor(
76                    isolate, Builtins::kLoadGlobalICInsideTypeofTrampoline);
77 }
78 
79 // static
LoadGlobalICInOptimizedCode(Isolate * isolate,TypeofMode typeof_mode)80 Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
81                                                   TypeofMode typeof_mode) {
82   return typeof_mode == NOT_INSIDE_TYPEOF
83              ? Builtins::CallableFor(isolate, Builtins::kLoadGlobalIC)
84              : Builtins::CallableFor(isolate,
85                                      Builtins::kLoadGlobalICInsideTypeof);
86 }
87 
StoreOwnIC(Isolate * isolate)88 Callable CodeFactory::StoreOwnIC(Isolate* isolate) {
89   // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
90   // already exist in the boilerplate therefore we can use StoreIC.
91   return Builtins::CallableFor(isolate, Builtins::kStoreICTrampoline);
92 }
93 
StoreOwnICInOptimizedCode(Isolate * isolate)94 Callable CodeFactory::StoreOwnICInOptimizedCode(Isolate* isolate) {
95   // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
96   // already exist in the boilerplate therefore we can use StoreIC.
97   return Builtins::CallableFor(isolate, Builtins::kStoreIC);
98 }
99 
KeyedStoreIC_SloppyArguments(Isolate * isolate,KeyedAccessStoreMode mode)100 Callable CodeFactory::KeyedStoreIC_SloppyArguments(Isolate* isolate,
101                                                    KeyedAccessStoreMode mode) {
102   Builtins::Name builtin_index;
103   switch (mode) {
104     case STANDARD_STORE:
105       builtin_index = Builtins::kKeyedStoreIC_SloppyArguments_Standard;
106       break;
107     case STORE_AND_GROW_HANDLE_COW:
108       builtin_index =
109           Builtins::kKeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW;
110       break;
111     case STORE_IGNORE_OUT_OF_BOUNDS:
112       builtin_index =
113           Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB;
114       break;
115     case STORE_HANDLE_COW:
116       builtin_index =
117           Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW;
118       break;
119     default:
120       UNREACHABLE();
121   }
122   return isolate->builtins()->CallableFor(isolate, builtin_index);
123 }
124 
ElementsTransitionAndStore(Isolate * isolate,KeyedAccessStoreMode mode)125 Callable CodeFactory::ElementsTransitionAndStore(Isolate* isolate,
126                                                  KeyedAccessStoreMode mode) {
127   Builtins::Name builtin_index;
128   switch (mode) {
129     case STANDARD_STORE:
130       builtin_index = Builtins::kElementsTransitionAndStore_Standard;
131       break;
132     case STORE_AND_GROW_HANDLE_COW:
133       builtin_index =
134           Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW;
135       break;
136     case STORE_IGNORE_OUT_OF_BOUNDS:
137       builtin_index =
138           Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB;
139       break;
140     case STORE_HANDLE_COW:
141       builtin_index =
142           Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW;
143       break;
144     default:
145       UNREACHABLE();
146   }
147   return isolate->builtins()->CallableFor(isolate, builtin_index);
148 }
149 
StoreFastElementIC(Isolate * isolate,KeyedAccessStoreMode mode)150 Callable CodeFactory::StoreFastElementIC(Isolate* isolate,
151                                          KeyedAccessStoreMode mode) {
152   Builtins::Name builtin_index;
153   switch (mode) {
154     case STANDARD_STORE:
155       builtin_index = Builtins::kStoreFastElementIC_Standard;
156       break;
157     case STORE_AND_GROW_HANDLE_COW:
158       builtin_index = Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW;
159       break;
160     case STORE_IGNORE_OUT_OF_BOUNDS:
161       builtin_index = Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB;
162       break;
163     case STORE_HANDLE_COW:
164       builtin_index = Builtins::kStoreFastElementIC_NoTransitionHandleCOW;
165       break;
166     default:
167       UNREACHABLE();
168   }
169   return isolate->builtins()->CallableFor(isolate, builtin_index);
170 }
171 
172 // static
BinaryOperation(Isolate * isolate,Operation op)173 Callable CodeFactory::BinaryOperation(Isolate* isolate, Operation op) {
174   switch (op) {
175     case Operation::kShiftRight:
176       return Builtins::CallableFor(isolate, Builtins::kShiftRight);
177     case Operation::kShiftLeft:
178       return Builtins::CallableFor(isolate, Builtins::kShiftLeft);
179     case Operation::kShiftRightLogical:
180       return Builtins::CallableFor(isolate, Builtins::kShiftRightLogical);
181     case Operation::kAdd:
182       return Builtins::CallableFor(isolate, Builtins::kAdd);
183     case Operation::kSubtract:
184       return Builtins::CallableFor(isolate, Builtins::kSubtract);
185     case Operation::kMultiply:
186       return Builtins::CallableFor(isolate, Builtins::kMultiply);
187     case Operation::kDivide:
188       return Builtins::CallableFor(isolate, Builtins::kDivide);
189     case Operation::kModulus:
190       return Builtins::CallableFor(isolate, Builtins::kModulus);
191     case Operation::kBitwiseOr:
192       return Builtins::CallableFor(isolate, Builtins::kBitwiseOr);
193     case Operation::kBitwiseAnd:
194       return Builtins::CallableFor(isolate, Builtins::kBitwiseAnd);
195     case Operation::kBitwiseXor:
196       return Builtins::CallableFor(isolate, Builtins::kBitwiseXor);
197     default:
198       break;
199   }
200   UNREACHABLE();
201 }
202 
203 // static
NonPrimitiveToPrimitive(Isolate * isolate,ToPrimitiveHint hint)204 Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
205                                               ToPrimitiveHint hint) {
206   return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
207                   TypeConversionDescriptor{});
208 }
209 
210 // static
OrdinaryToPrimitive(Isolate * isolate,OrdinaryToPrimitiveHint hint)211 Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
212                                           OrdinaryToPrimitiveHint hint) {
213   return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
214                   TypeConversionDescriptor{});
215 }
216 
217 // static
StringAdd(Isolate * isolate,StringAddFlags flags)218 Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags) {
219   switch (flags) {
220     case STRING_ADD_CHECK_NONE:
221       return Builtins::CallableFor(isolate, Builtins::kStringAdd_CheckNone);
222     case STRING_ADD_CONVERT_LEFT:
223       return Builtins::CallableFor(isolate, Builtins::kStringAddConvertLeft);
224     case STRING_ADD_CONVERT_RIGHT:
225       return Builtins::CallableFor(isolate, Builtins::kStringAddConvertRight);
226   }
227   UNREACHABLE();
228 }
229 
230 // static
ResumeGenerator(Isolate * isolate)231 Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
232   return Builtins::CallableFor(isolate, Builtins::kResumeGeneratorTrampoline);
233 }
234 
235 // static
FrameDropperTrampoline(Isolate * isolate)236 Callable CodeFactory::FrameDropperTrampoline(Isolate* isolate) {
237   return Builtins::CallableFor(isolate, Builtins::kFrameDropperTrampoline);
238 }
239 
240 // static
HandleDebuggerStatement(Isolate * isolate)241 Callable CodeFactory::HandleDebuggerStatement(Isolate* isolate) {
242   return Builtins::CallableFor(isolate, Builtins::kHandleDebuggerStatement);
243 }
244 
245 // static
FastNewFunctionContext(Isolate * isolate,ScopeType scope_type)246 Callable CodeFactory::FastNewFunctionContext(Isolate* isolate,
247                                              ScopeType scope_type) {
248   switch (scope_type) {
249     case ScopeType::EVAL_SCOPE:
250       return Builtins::CallableFor(isolate,
251                                    Builtins::kFastNewFunctionContextEval);
252     case ScopeType::FUNCTION_SCOPE:
253       return Builtins::CallableFor(isolate,
254                                    Builtins::kFastNewFunctionContextFunction);
255     default:
256       UNREACHABLE();
257   }
258 }
259 
260 // static
ArgumentAdaptor(Isolate * isolate)261 Callable CodeFactory::ArgumentAdaptor(Isolate* isolate) {
262   return Builtins::CallableFor(isolate, Builtins::kArgumentsAdaptorTrampoline);
263 }
264 
265 // static
Call(Isolate * isolate,ConvertReceiverMode mode)266 Callable CodeFactory::Call(Isolate* isolate, ConvertReceiverMode mode) {
267   return Callable(isolate->builtins()->Call(mode), CallTrampolineDescriptor{});
268 }
269 
270 // static
Call_WithFeedback(Isolate * isolate,ConvertReceiverMode mode)271 Callable CodeFactory::Call_WithFeedback(Isolate* isolate,
272                                         ConvertReceiverMode mode) {
273   switch (mode) {
274     case ConvertReceiverMode::kNullOrUndefined:
275       return Builtins::CallableFor(
276           isolate, Builtins::kCall_ReceiverIsNullOrUndefined_WithFeedback);
277     case ConvertReceiverMode::kNotNullOrUndefined:
278       return Builtins::CallableFor(
279           isolate, Builtins::kCall_ReceiverIsNotNullOrUndefined_WithFeedback);
280     case ConvertReceiverMode::kAny:
281       return Builtins::CallableFor(isolate,
282                                    Builtins::kCall_ReceiverIsAny_WithFeedback);
283   }
284   UNREACHABLE();
285 }
286 
287 // static
CallWithArrayLike(Isolate * isolate)288 Callable CodeFactory::CallWithArrayLike(Isolate* isolate) {
289   return Builtins::CallableFor(isolate, Builtins::kCallWithArrayLike);
290 }
291 
292 // static
CallWithSpread(Isolate * isolate)293 Callable CodeFactory::CallWithSpread(Isolate* isolate) {
294   return Builtins::CallableFor(isolate, Builtins::kCallWithSpread);
295 }
296 
297 // static
CallFunction(Isolate * isolate,ConvertReceiverMode mode)298 Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode) {
299   return Callable(isolate->builtins()->CallFunction(mode),
300                   CallTrampolineDescriptor{});
301 }
302 
303 // static
CallVarargs(Isolate * isolate)304 Callable CodeFactory::CallVarargs(Isolate* isolate) {
305   return Builtins::CallableFor(isolate, Builtins::kCallVarargs);
306 }
307 
308 // static
CallForwardVarargs(Isolate * isolate)309 Callable CodeFactory::CallForwardVarargs(Isolate* isolate) {
310   return Builtins::CallableFor(isolate, Builtins::kCallForwardVarargs);
311 }
312 
313 // static
CallFunctionForwardVarargs(Isolate * isolate)314 Callable CodeFactory::CallFunctionForwardVarargs(Isolate* isolate) {
315   return Builtins::CallableFor(isolate, Builtins::kCallFunctionForwardVarargs);
316 }
317 
318 // static
Construct(Isolate * isolate)319 Callable CodeFactory::Construct(Isolate* isolate) {
320   return Builtins::CallableFor(isolate, Builtins::kConstruct);
321 }
322 
323 // static
ConstructWithSpread(Isolate * isolate)324 Callable CodeFactory::ConstructWithSpread(Isolate* isolate) {
325   return Builtins::CallableFor(isolate, Builtins::kConstructWithSpread);
326 }
327 
328 // static
ConstructFunction(Isolate * isolate)329 Callable CodeFactory::ConstructFunction(Isolate* isolate) {
330   return Builtins::CallableFor(isolate, Builtins::kConstructFunction);
331 }
332 
333 // static
ConstructVarargs(Isolate * isolate)334 Callable CodeFactory::ConstructVarargs(Isolate* isolate) {
335   return Builtins::CallableFor(isolate, Builtins::kConstructVarargs);
336 }
337 
338 // static
ConstructForwardVarargs(Isolate * isolate)339 Callable CodeFactory::ConstructForwardVarargs(Isolate* isolate) {
340   return Builtins::CallableFor(isolate, Builtins::kConstructForwardVarargs);
341 }
342 
343 // static
ConstructFunctionForwardVarargs(Isolate * isolate)344 Callable CodeFactory::ConstructFunctionForwardVarargs(Isolate* isolate) {
345   return Builtins::CallableFor(isolate,
346                                Builtins::kConstructFunctionForwardVarargs);
347 }
348 
349 // static
InterpreterPushArgsThenCall(Isolate * isolate,ConvertReceiverMode receiver_mode,InterpreterPushArgsMode mode)350 Callable CodeFactory::InterpreterPushArgsThenCall(
351     Isolate* isolate, ConvertReceiverMode receiver_mode,
352     InterpreterPushArgsMode mode) {
353   switch (mode) {
354     case InterpreterPushArgsMode::kArrayFunction:
355       // There is no special-case handling of calls to Array. They will all go
356       // through the kOther case below.
357       UNREACHABLE();
358     case InterpreterPushArgsMode::kWithFinalSpread:
359       return Builtins::CallableFor(
360           isolate, Builtins::kInterpreterPushArgsThenCallWithFinalSpread);
361     case InterpreterPushArgsMode::kOther:
362       switch (receiver_mode) {
363         case ConvertReceiverMode::kNullOrUndefined:
364           return Builtins::CallableFor(
365               isolate, Builtins::kInterpreterPushUndefinedAndArgsThenCall);
366         case ConvertReceiverMode::kNotNullOrUndefined:
367         case ConvertReceiverMode::kAny:
368           return Builtins::CallableFor(isolate,
369                                        Builtins::kInterpreterPushArgsThenCall);
370       }
371   }
372   UNREACHABLE();
373 }
374 
375 // static
InterpreterPushArgsThenConstruct(Isolate * isolate,InterpreterPushArgsMode mode)376 Callable CodeFactory::InterpreterPushArgsThenConstruct(
377     Isolate* isolate, InterpreterPushArgsMode mode) {
378   switch (mode) {
379     case InterpreterPushArgsMode::kArrayFunction:
380       return Builtins::CallableFor(
381           isolate, Builtins::kInterpreterPushArgsThenConstructArrayFunction);
382     case InterpreterPushArgsMode::kWithFinalSpread:
383       return Builtins::CallableFor(
384           isolate, Builtins::kInterpreterPushArgsThenConstructWithFinalSpread);
385     case InterpreterPushArgsMode::kOther:
386       return Builtins::CallableFor(isolate,
387                                    Builtins::kInterpreterPushArgsThenConstruct);
388   }
389   UNREACHABLE();
390 }
391 
392 // static
InterpreterCEntry(Isolate * isolate,int result_size)393 Callable CodeFactory::InterpreterCEntry(Isolate* isolate, int result_size) {
394   // Note: If we ever use fpregs in the interpreter then we will need to
395   // save fpregs too.
396   Handle<Code> code = CodeFactory::CEntry(isolate, result_size, kDontSaveFPRegs,
397                                           kArgvInRegister);
398   if (result_size == 1) {
399     return Callable(code, InterpreterCEntry1Descriptor{});
400   } else {
401     DCHECK_EQ(result_size, 2);
402     return Callable(code, InterpreterCEntry2Descriptor{});
403   }
404 }
405 
406 // static
InterpreterOnStackReplacement(Isolate * isolate)407 Callable CodeFactory::InterpreterOnStackReplacement(Isolate* isolate) {
408   return Builtins::CallableFor(isolate,
409                                Builtins::kInterpreterOnStackReplacement);
410 }
411 
412 // static
ArrayNoArgumentConstructor(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)413 Callable CodeFactory::ArrayNoArgumentConstructor(
414     Isolate* isolate, ElementsKind kind,
415     AllocationSiteOverrideMode override_mode) {
416 #define CASE(kind_caps, kind_camel, mode_camel) \
417   case kind_caps:                               \
418     return Builtins::CallableFor(               \
419         isolate,                                \
420         Builtins::kArrayNoArgumentConstructor_##kind_camel##_##mode_camel);
421   if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
422     DCHECK(IsSmiElementsKind(kind));
423     switch (kind) {
424       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
425       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
426       default:
427         UNREACHABLE();
428     }
429   } else {
430     DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
431            !AllocationSite::ShouldTrack(kind));
432     switch (kind) {
433       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
434       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
435       CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
436       CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
437       CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
438       CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
439       default:
440         UNREACHABLE();
441     }
442   }
443 #undef CASE
444 }
445 
446 // static
ArraySingleArgumentConstructor(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)447 Callable CodeFactory::ArraySingleArgumentConstructor(
448     Isolate* isolate, ElementsKind kind,
449     AllocationSiteOverrideMode override_mode) {
450 #define CASE(kind_caps, kind_camel, mode_camel) \
451   case kind_caps:                               \
452     return Builtins::CallableFor(               \
453         isolate,                                \
454         Builtins::kArraySingleArgumentConstructor_##kind_camel##_##mode_camel)
455   if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
456     DCHECK(IsSmiElementsKind(kind));
457     switch (kind) {
458       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
459       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
460       default:
461         UNREACHABLE();
462     }
463   } else {
464     DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
465            !AllocationSite::ShouldTrack(kind));
466     switch (kind) {
467       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
468       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
469       CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
470       CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
471       CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
472       CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
473       default:
474         UNREACHABLE();
475     }
476   }
477 #undef CASE
478 }
479 
480 }  // namespace internal
481 }  // namespace v8
482