• 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<CodeT> 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<CodeT> 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 == SaveFPRegsMode::kIgnore && am == ArgvMode::kStack &&
35       !be) {
36     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
37   } else if (rs == 1 && sd == SaveFPRegsMode::kIgnore &&
38              am == ArgvMode::kStack && be) {
39     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
40   } else if (rs == 1 && sd == SaveFPRegsMode::kIgnore &&
41              am == ArgvMode::kRegister && !be) {
42     return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
43   } else if (rs == 1 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
44              !be) {
45     return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
46   } else if (rs == 1 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
47              be) {
48     return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, BuiltinExit);
49   } else if (rs == 2 && sd == SaveFPRegsMode::kIgnore &&
50              am == ArgvMode::kStack && !be) {
51     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
52   } else if (rs == 2 && sd == SaveFPRegsMode::kIgnore &&
53              am == ArgvMode::kStack && be) {
54     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
55   } else if (rs == 2 && sd == SaveFPRegsMode::kIgnore &&
56              am == ArgvMode::kRegister && !be) {
57     return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
58   } else if (rs == 2 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
59              !be) {
60     return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
61   } else if (rs == 2 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
62              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   return Builtins::CallableFor(isolate, Builtin::kCallApiGetter);
74 }
75 
76 // static
CallApiCallback(Isolate * isolate)77 Callable CodeFactory::CallApiCallback(Isolate* isolate) {
78   return Builtins::CallableFor(isolate, Builtin::kCallApiCallback);
79 }
80 
81 // static
LoadGlobalIC(Isolate * isolate,TypeofMode typeof_mode)82 Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
83   return typeof_mode == TypeofMode::kNotInside
84              ? Builtins::CallableFor(isolate, Builtin::kLoadGlobalICTrampoline)
85              : Builtins::CallableFor(
86                    isolate, Builtin::kLoadGlobalICInsideTypeofTrampoline);
87 }
88 
89 // static
LoadGlobalICInOptimizedCode(Isolate * isolate,TypeofMode typeof_mode)90 Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
91                                                   TypeofMode typeof_mode) {
92   return typeof_mode == TypeofMode::kNotInside
93              ? Builtins::CallableFor(isolate, Builtin::kLoadGlobalIC)
94              : Builtins::CallableFor(isolate,
95                                      Builtin::kLoadGlobalICInsideTypeof);
96 }
97 
DefineNamedOwnIC(Isolate * isolate)98 Callable CodeFactory::DefineNamedOwnIC(Isolate* isolate) {
99   return Builtins::CallableFor(isolate, Builtin::kDefineNamedOwnICTrampoline);
100 }
101 
DefineNamedOwnICInOptimizedCode(Isolate * isolate)102 Callable CodeFactory::DefineNamedOwnICInOptimizedCode(Isolate* isolate) {
103   return Builtins::CallableFor(isolate, Builtin::kDefineNamedOwnIC);
104 }
105 
106 // static
NonPrimitiveToPrimitive(Isolate * isolate,ToPrimitiveHint hint)107 Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
108                                               ToPrimitiveHint hint) {
109   return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
110                   TypeConversionDescriptor{});
111 }
112 
113 // static
OrdinaryToPrimitive(Isolate * isolate,OrdinaryToPrimitiveHint hint)114 Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
115                                           OrdinaryToPrimitiveHint hint) {
116   return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
117                   TypeConversionDescriptor{});
118 }
119 
120 // static
StringAdd(Isolate * isolate,StringAddFlags flags)121 Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags) {
122   switch (flags) {
123     case STRING_ADD_CHECK_NONE:
124       return Builtins::CallableFor(isolate, Builtin::kStringAdd_CheckNone);
125     case STRING_ADD_CONVERT_LEFT:
126       return Builtins::CallableFor(isolate, Builtin::kStringAddConvertLeft);
127     case STRING_ADD_CONVERT_RIGHT:
128       return Builtins::CallableFor(isolate, Builtin::kStringAddConvertRight);
129   }
130   UNREACHABLE();
131 }
132 
133 // static
ResumeGenerator(Isolate * isolate)134 Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
135   return Builtins::CallableFor(isolate, Builtin::kResumeGeneratorTrampoline);
136 }
137 
138 // static
FastNewFunctionContext(Isolate * isolate,ScopeType scope_type)139 Callable CodeFactory::FastNewFunctionContext(Isolate* isolate,
140                                              ScopeType scope_type) {
141   switch (scope_type) {
142     case ScopeType::EVAL_SCOPE:
143       return Builtins::CallableFor(isolate,
144                                    Builtin::kFastNewFunctionContextEval);
145     case ScopeType::FUNCTION_SCOPE:
146       return Builtins::CallableFor(isolate,
147                                    Builtin::kFastNewFunctionContextFunction);
148     default:
149       UNREACHABLE();
150   }
151 }
152 
153 // static
Call(Isolate * isolate,ConvertReceiverMode mode)154 Callable CodeFactory::Call(Isolate* isolate, ConvertReceiverMode mode) {
155   return Callable(isolate->builtins()->Call(mode), CallTrampolineDescriptor{});
156 }
157 
158 // static
Call_WithFeedback(Isolate * isolate,ConvertReceiverMode mode)159 Callable CodeFactory::Call_WithFeedback(Isolate* isolate,
160                                         ConvertReceiverMode mode) {
161   switch (mode) {
162     case ConvertReceiverMode::kNullOrUndefined:
163       return Builtins::CallableFor(
164           isolate, Builtin::kCall_ReceiverIsNullOrUndefined_WithFeedback);
165     case ConvertReceiverMode::kNotNullOrUndefined:
166       return Builtins::CallableFor(
167           isolate, Builtin::kCall_ReceiverIsNotNullOrUndefined_WithFeedback);
168     case ConvertReceiverMode::kAny:
169       return Builtins::CallableFor(isolate,
170                                    Builtin::kCall_ReceiverIsAny_WithFeedback);
171   }
172   UNREACHABLE();
173 }
174 
175 // static
CallWithArrayLike(Isolate * isolate)176 Callable CodeFactory::CallWithArrayLike(Isolate* isolate) {
177   return Builtins::CallableFor(isolate, Builtin::kCallWithArrayLike);
178 }
179 
180 // static
CallWithSpread(Isolate * isolate)181 Callable CodeFactory::CallWithSpread(Isolate* isolate) {
182   return Builtins::CallableFor(isolate, Builtin::kCallWithSpread);
183 }
184 
185 // static
CallFunction(Isolate * isolate,ConvertReceiverMode mode)186 Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode) {
187   return Callable(isolate->builtins()->CallFunction(mode),
188                   CallTrampolineDescriptor{});
189 }
190 
191 // static
CallVarargs(Isolate * isolate)192 Callable CodeFactory::CallVarargs(Isolate* isolate) {
193   return Builtins::CallableFor(isolate, Builtin::kCallVarargs);
194 }
195 
196 // static
CallForwardVarargs(Isolate * isolate)197 Callable CodeFactory::CallForwardVarargs(Isolate* isolate) {
198   return Builtins::CallableFor(isolate, Builtin::kCallForwardVarargs);
199 }
200 
201 // static
CallFunctionForwardVarargs(Isolate * isolate)202 Callable CodeFactory::CallFunctionForwardVarargs(Isolate* isolate) {
203   return Builtins::CallableFor(isolate, Builtin::kCallFunctionForwardVarargs);
204 }
205 
206 // static
Construct(Isolate * isolate)207 Callable CodeFactory::Construct(Isolate* isolate) {
208   return Builtins::CallableFor(isolate, Builtin::kConstruct);
209 }
210 
211 // static
ConstructWithSpread(Isolate * isolate)212 Callable CodeFactory::ConstructWithSpread(Isolate* isolate) {
213   return Builtins::CallableFor(isolate, Builtin::kConstructWithSpread);
214 }
215 
216 // static
ConstructFunction(Isolate * isolate)217 Callable CodeFactory::ConstructFunction(Isolate* isolate) {
218   return Builtins::CallableFor(isolate, Builtin::kConstructFunction);
219 }
220 
221 // static
ConstructVarargs(Isolate * isolate)222 Callable CodeFactory::ConstructVarargs(Isolate* isolate) {
223   return Builtins::CallableFor(isolate, Builtin::kConstructVarargs);
224 }
225 
226 // static
ConstructForwardVarargs(Isolate * isolate)227 Callable CodeFactory::ConstructForwardVarargs(Isolate* isolate) {
228   return Builtins::CallableFor(isolate, Builtin::kConstructForwardVarargs);
229 }
230 
231 // static
ConstructFunctionForwardVarargs(Isolate * isolate)232 Callable CodeFactory::ConstructFunctionForwardVarargs(Isolate* isolate) {
233   return Builtins::CallableFor(isolate,
234                                Builtin::kConstructFunctionForwardVarargs);
235 }
236 
237 // static
InterpreterPushArgsThenCall(Isolate * isolate,ConvertReceiverMode receiver_mode,InterpreterPushArgsMode mode)238 Callable CodeFactory::InterpreterPushArgsThenCall(
239     Isolate* isolate, ConvertReceiverMode receiver_mode,
240     InterpreterPushArgsMode mode) {
241   switch (mode) {
242     case InterpreterPushArgsMode::kArrayFunction:
243       // There is no special-case handling of calls to Array. They will all go
244       // through the kOther case below.
245       UNREACHABLE();
246     case InterpreterPushArgsMode::kWithFinalSpread:
247       return Builtins::CallableFor(
248           isolate, Builtin::kInterpreterPushArgsThenCallWithFinalSpread);
249     case InterpreterPushArgsMode::kOther:
250       switch (receiver_mode) {
251         case ConvertReceiverMode::kNullOrUndefined:
252           return Builtins::CallableFor(
253               isolate, Builtin::kInterpreterPushUndefinedAndArgsThenCall);
254         case ConvertReceiverMode::kNotNullOrUndefined:
255         case ConvertReceiverMode::kAny:
256           return Builtins::CallableFor(isolate,
257                                        Builtin::kInterpreterPushArgsThenCall);
258       }
259   }
260   UNREACHABLE();
261 }
262 
263 // static
InterpreterPushArgsThenConstruct(Isolate * isolate,InterpreterPushArgsMode mode)264 Callable CodeFactory::InterpreterPushArgsThenConstruct(
265     Isolate* isolate, InterpreterPushArgsMode mode) {
266   switch (mode) {
267     case InterpreterPushArgsMode::kArrayFunction:
268       return Builtins::CallableFor(
269           isolate, Builtin::kInterpreterPushArgsThenConstructArrayFunction);
270     case InterpreterPushArgsMode::kWithFinalSpread:
271       return Builtins::CallableFor(
272           isolate, Builtin::kInterpreterPushArgsThenConstructWithFinalSpread);
273     case InterpreterPushArgsMode::kOther:
274       return Builtins::CallableFor(isolate,
275                                    Builtin::kInterpreterPushArgsThenConstruct);
276   }
277   UNREACHABLE();
278 }
279 
280 // static
InterpreterCEntry(Isolate * isolate,int result_size)281 Callable CodeFactory::InterpreterCEntry(Isolate* isolate, int result_size) {
282   // Note: If we ever use fpregs in the interpreter then we will need to
283   // save fpregs too.
284   Handle<CodeT> code = CodeFactory::CEntry(
285       isolate, result_size, SaveFPRegsMode::kIgnore, ArgvMode::kRegister);
286   if (result_size == 1) {
287     return Callable(code, InterpreterCEntry1Descriptor{});
288   } else {
289     DCHECK_EQ(result_size, 2);
290     return Callable(code, InterpreterCEntry2Descriptor{});
291   }
292 }
293 
294 // static
InterpreterOnStackReplacement(Isolate * isolate)295 Callable CodeFactory::InterpreterOnStackReplacement(Isolate* isolate) {
296   return Builtins::CallableFor(isolate,
297                                Builtin::kInterpreterOnStackReplacement);
298 }
299 
300 // static
InterpreterOnStackReplacement_ToBaseline(Isolate * isolate)301 Callable CodeFactory::InterpreterOnStackReplacement_ToBaseline(
302     Isolate* isolate) {
303   return Builtins::CallableFor(
304       isolate, Builtin::kInterpreterOnStackReplacement_ToBaseline);
305 }
306 
307 // static
ArrayNoArgumentConstructor(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)308 Callable CodeFactory::ArrayNoArgumentConstructor(
309     Isolate* isolate, ElementsKind kind,
310     AllocationSiteOverrideMode override_mode) {
311 #define CASE(kind_caps, kind_camel, mode_camel) \
312   case kind_caps:                               \
313     return Builtins::CallableFor(               \
314         isolate,                                \
315         Builtin::kArrayNoArgumentConstructor_##kind_camel##_##mode_camel);
316   if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
317     DCHECK(IsSmiElementsKind(kind));
318     switch (kind) {
319       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
320       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
321       default:
322         UNREACHABLE();
323     }
324   } else {
325     DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
326            !AllocationSite::ShouldTrack(kind));
327     switch (kind) {
328       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
329       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
330       CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
331       CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
332       CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
333       CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
334       default:
335         UNREACHABLE();
336     }
337   }
338 #undef CASE
339 }
340 
341 // static
ArraySingleArgumentConstructor(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)342 Callable CodeFactory::ArraySingleArgumentConstructor(
343     Isolate* isolate, ElementsKind kind,
344     AllocationSiteOverrideMode override_mode) {
345 #define CASE(kind_caps, kind_camel, mode_camel) \
346   case kind_caps:                               \
347     return Builtins::CallableFor(               \
348         isolate,                                \
349         Builtin::kArraySingleArgumentConstructor_##kind_camel##_##mode_camel)
350   if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
351     DCHECK(IsSmiElementsKind(kind));
352     switch (kind) {
353       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
354       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
355       default:
356         UNREACHABLE();
357     }
358   } else {
359     DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
360            !AllocationSite::ShouldTrack(kind));
361     switch (kind) {
362       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
363       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
364       CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
365       CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
366       CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
367       CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
368       default:
369         UNREACHABLE();
370     }
371   }
372 #undef CASE
373 }
374 
375 #ifdef V8_IS_TSAN
376 // static
GetTSANStoreStub(SaveFPRegsMode fp_mode,int size,std::memory_order order)377 Builtin CodeFactory::GetTSANStoreStub(SaveFPRegsMode fp_mode, int size,
378                                       std::memory_order order) {
379   if (order == std::memory_order_relaxed) {
380     if (size == kInt8Size) {
381       return fp_mode == SaveFPRegsMode::kIgnore
382                  ? Builtin::kTSANRelaxedStore8IgnoreFP
383                  : Builtin::kTSANRelaxedStore8SaveFP;
384     } else if (size == kInt16Size) {
385       return fp_mode == SaveFPRegsMode::kIgnore
386                  ? Builtin::kTSANRelaxedStore16IgnoreFP
387                  : Builtin::kTSANRelaxedStore16SaveFP;
388     } else if (size == kInt32Size) {
389       return fp_mode == SaveFPRegsMode::kIgnore
390                  ? Builtin::kTSANRelaxedStore32IgnoreFP
391                  : Builtin::kTSANRelaxedStore32SaveFP;
392     } else {
393       CHECK_EQ(size, kInt64Size);
394       return fp_mode == SaveFPRegsMode::kIgnore
395                  ? Builtin::kTSANRelaxedStore64IgnoreFP
396                  : Builtin::kTSANRelaxedStore64SaveFP;
397     }
398   } else {
399     DCHECK_EQ(order, std::memory_order_seq_cst);
400     if (size == kInt8Size) {
401       return fp_mode == SaveFPRegsMode::kIgnore
402                  ? Builtin::kTSANSeqCstStore8IgnoreFP
403                  : Builtin::kTSANSeqCstStore8SaveFP;
404     } else if (size == kInt16Size) {
405       return fp_mode == SaveFPRegsMode::kIgnore
406                  ? Builtin::kTSANSeqCstStore16IgnoreFP
407                  : Builtin::kTSANSeqCstStore16SaveFP;
408     } else if (size == kInt32Size) {
409       return fp_mode == SaveFPRegsMode::kIgnore
410                  ? Builtin::kTSANSeqCstStore32IgnoreFP
411                  : Builtin::kTSANSeqCstStore32SaveFP;
412     } else {
413       CHECK_EQ(size, kInt64Size);
414       return fp_mode == SaveFPRegsMode::kIgnore
415                  ? Builtin::kTSANSeqCstStore64IgnoreFP
416                  : Builtin::kTSANSeqCstStore64SaveFP;
417     }
418   }
419 }
420 
421 // static
GetTSANRelaxedLoadStub(SaveFPRegsMode fp_mode,int size)422 Builtin CodeFactory::GetTSANRelaxedLoadStub(SaveFPRegsMode fp_mode, int size) {
423   if (size == kInt32Size) {
424     return fp_mode == SaveFPRegsMode::kIgnore
425                ? Builtin::kTSANRelaxedLoad32IgnoreFP
426                : Builtin::kTSANRelaxedLoad32SaveFP;
427   } else {
428     CHECK_EQ(size, kInt64Size);
429     return fp_mode == SaveFPRegsMode::kIgnore
430                ? Builtin::kTSANRelaxedLoad64IgnoreFP
431                : Builtin::kTSANRelaxedLoad64SaveFP;
432   }
433 }
434 #endif  // V8_IS_TSAN
435 
436 }  // namespace internal
437 }  // namespace v8
438