• 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/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{});
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   return Callable(BUILTIN_CODE(isolate, CallApiGetter), ApiGetterDescriptor{});
74 }
75 
76 // static
CallApiCallback(Isolate * isolate,int argc)77 Callable CodeFactory::CallApiCallback(Isolate* isolate, int argc) {
78   switch (argc) {
79     case 0:
80       return Callable(BUILTIN_CODE(isolate, CallApiCallback_Argc0),
81                       ApiCallbackDescriptor{});
82     case 1:
83       return Callable(BUILTIN_CODE(isolate, CallApiCallback_Argc1),
84                       ApiCallbackDescriptor{});
85     default: {
86       CallApiCallbackStub stub(isolate, argc);
87       return make_callable(stub);
88     }
89   }
90   UNREACHABLE();
91 }
92 
93 // static
LoadGlobalIC(Isolate * isolate,TypeofMode typeof_mode)94 Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
95   return Callable(
96       typeof_mode == NOT_INSIDE_TYPEOF
97           ? BUILTIN_CODE(isolate, LoadGlobalICTrampoline)
98           : BUILTIN_CODE(isolate, LoadGlobalICInsideTypeofTrampoline),
99       LoadGlobalDescriptor{});
100 }
101 
102 // static
LoadGlobalICInOptimizedCode(Isolate * isolate,TypeofMode typeof_mode)103 Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
104                                                   TypeofMode typeof_mode) {
105   return Callable(typeof_mode == NOT_INSIDE_TYPEOF
106                       ? BUILTIN_CODE(isolate, LoadGlobalIC)
107                       : BUILTIN_CODE(isolate, LoadGlobalICInsideTypeof),
108                   LoadGlobalWithVectorDescriptor{});
109 }
110 
StoreOwnIC(Isolate * isolate)111 Callable CodeFactory::StoreOwnIC(Isolate* isolate) {
112   // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
113   // already exist in the boilerplate therefore we can use StoreIC.
114   return Callable(BUILTIN_CODE(isolate, StoreICTrampoline), StoreDescriptor{});
115 }
116 
StoreOwnICInOptimizedCode(Isolate * isolate)117 Callable CodeFactory::StoreOwnICInOptimizedCode(Isolate* isolate) {
118   // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
119   // already exist in the boilerplate therefore we can use StoreIC.
120   return Callable(BUILTIN_CODE(isolate, StoreIC), StoreWithVectorDescriptor{});
121 }
122 
123 // static
BinaryOperation(Isolate * isolate,Operation op)124 Callable CodeFactory::BinaryOperation(Isolate* isolate, Operation op) {
125   switch (op) {
126     case Operation::kShiftRight:
127       return Builtins::CallableFor(isolate, Builtins::kShiftRight);
128     case Operation::kShiftLeft:
129       return Builtins::CallableFor(isolate, Builtins::kShiftLeft);
130     case Operation::kShiftRightLogical:
131       return Builtins::CallableFor(isolate, Builtins::kShiftRightLogical);
132     case Operation::kAdd:
133       return Builtins::CallableFor(isolate, Builtins::kAdd);
134     case Operation::kSubtract:
135       return Builtins::CallableFor(isolate, Builtins::kSubtract);
136     case Operation::kMultiply:
137       return Builtins::CallableFor(isolate, Builtins::kMultiply);
138     case Operation::kDivide:
139       return Builtins::CallableFor(isolate, Builtins::kDivide);
140     case Operation::kModulus:
141       return Builtins::CallableFor(isolate, Builtins::kModulus);
142     case Operation::kBitwiseOr:
143       return Builtins::CallableFor(isolate, Builtins::kBitwiseOr);
144     case Operation::kBitwiseAnd:
145       return Builtins::CallableFor(isolate, Builtins::kBitwiseAnd);
146     case Operation::kBitwiseXor:
147       return Builtins::CallableFor(isolate, Builtins::kBitwiseXor);
148     default:
149       break;
150   }
151   UNREACHABLE();
152 }
153 
154 // static
NonPrimitiveToPrimitive(Isolate * isolate,ToPrimitiveHint hint)155 Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
156                                               ToPrimitiveHint hint) {
157   return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
158                   TypeConversionDescriptor{});
159 }
160 
161 // static
OrdinaryToPrimitive(Isolate * isolate,OrdinaryToPrimitiveHint hint)162 Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
163                                           OrdinaryToPrimitiveHint hint) {
164   return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
165                   TypeConversionDescriptor{});
166 }
167 
168 // static
StringAdd(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)169 Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
170                                 PretenureFlag pretenure_flag) {
171   if (pretenure_flag == NOT_TENURED) {
172     switch (flags) {
173       case STRING_ADD_CHECK_NONE:
174         return Builtins::CallableFor(isolate,
175                                      Builtins::kStringAdd_CheckNone_NotTenured);
176       case STRING_ADD_CONVERT_LEFT:
177         return Builtins::CallableFor(
178             isolate, Builtins::kStringAdd_ConvertLeft_NotTenured);
179       case STRING_ADD_CONVERT_RIGHT:
180         return Builtins::CallableFor(
181             isolate, Builtins::kStringAdd_ConvertRight_NotTenured);
182     }
183   } else {
184     CHECK_EQ(TENURED, pretenure_flag);
185     CHECK_EQ(STRING_ADD_CHECK_NONE, flags);
186     return Builtins::CallableFor(isolate,
187                                  Builtins::kStringAdd_CheckNone_Tenured);
188   }
189 
190   UNREACHABLE();
191 }
192 
193 // static
ResumeGenerator(Isolate * isolate)194 Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
195   return Callable(BUILTIN_CODE(isolate, ResumeGeneratorTrampoline),
196                   ResumeGeneratorDescriptor{});
197 }
198 
199 // static
FrameDropperTrampoline(Isolate * isolate)200 Callable CodeFactory::FrameDropperTrampoline(Isolate* isolate) {
201   return Callable(BUILTIN_CODE(isolate, FrameDropperTrampoline),
202                   FrameDropperTrampolineDescriptor{});
203 }
204 
205 // static
HandleDebuggerStatement(Isolate * isolate)206 Callable CodeFactory::HandleDebuggerStatement(Isolate* isolate) {
207   return Callable(BUILTIN_CODE(isolate, HandleDebuggerStatement),
208                   ContextOnlyDescriptor{});
209 }
210 
211 // static
FastNewFunctionContext(Isolate * isolate,ScopeType scope_type)212 Callable CodeFactory::FastNewFunctionContext(Isolate* isolate,
213                                              ScopeType scope_type) {
214   return Callable(isolate->builtins()->NewFunctionContext(scope_type),
215                   FastNewFunctionContextDescriptor{});
216 }
217 
218 // static
ArgumentAdaptor(Isolate * isolate)219 Callable CodeFactory::ArgumentAdaptor(Isolate* isolate) {
220   return Callable(BUILTIN_CODE(isolate, ArgumentsAdaptorTrampoline),
221                   ArgumentAdaptorDescriptor{});
222 }
223 
224 // static
Call(Isolate * isolate,ConvertReceiverMode mode)225 Callable CodeFactory::Call(Isolate* isolate, ConvertReceiverMode mode) {
226   return Callable(isolate->builtins()->Call(mode), CallTrampolineDescriptor{});
227 }
228 
229 // static
CallWithArrayLike(Isolate * isolate)230 Callable CodeFactory::CallWithArrayLike(Isolate* isolate) {
231   return Callable(BUILTIN_CODE(isolate, CallWithArrayLike),
232                   CallWithArrayLikeDescriptor{});
233 }
234 
235 // static
CallWithSpread(Isolate * isolate)236 Callable CodeFactory::CallWithSpread(Isolate* isolate) {
237   return Callable(BUILTIN_CODE(isolate, CallWithSpread),
238                   CallWithSpreadDescriptor{});
239 }
240 
241 // static
CallFunction(Isolate * isolate,ConvertReceiverMode mode)242 Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode) {
243   return Callable(isolate->builtins()->CallFunction(mode),
244                   CallTrampolineDescriptor{});
245 }
246 
247 // static
CallVarargs(Isolate * isolate)248 Callable CodeFactory::CallVarargs(Isolate* isolate) {
249   return Callable(BUILTIN_CODE(isolate, CallVarargs), CallVarargsDescriptor{});
250 }
251 
252 // static
CallForwardVarargs(Isolate * isolate)253 Callable CodeFactory::CallForwardVarargs(Isolate* isolate) {
254   return Callable(BUILTIN_CODE(isolate, CallForwardVarargs),
255                   CallForwardVarargsDescriptor{});
256 }
257 
258 // static
CallFunctionForwardVarargs(Isolate * isolate)259 Callable CodeFactory::CallFunctionForwardVarargs(Isolate* isolate) {
260   return Callable(BUILTIN_CODE(isolate, CallFunctionForwardVarargs),
261                   CallForwardVarargsDescriptor{});
262 }
263 
264 // static
Construct(Isolate * isolate)265 Callable CodeFactory::Construct(Isolate* isolate) {
266   return Callable(BUILTIN_CODE(isolate, Construct), JSTrampolineDescriptor{});
267 }
268 
269 // static
ConstructWithSpread(Isolate * isolate)270 Callable CodeFactory::ConstructWithSpread(Isolate* isolate) {
271   return Callable(BUILTIN_CODE(isolate, ConstructWithSpread),
272                   ConstructWithSpreadDescriptor{});
273 }
274 
275 // static
ConstructFunction(Isolate * isolate)276 Callable CodeFactory::ConstructFunction(Isolate* isolate) {
277   return Callable(BUILTIN_CODE(isolate, ConstructFunction),
278                   JSTrampolineDescriptor{});
279 }
280 
281 // static
ConstructVarargs(Isolate * isolate)282 Callable CodeFactory::ConstructVarargs(Isolate* isolate) {
283   return Callable(BUILTIN_CODE(isolate, ConstructVarargs),
284                   ConstructVarargsDescriptor{});
285 }
286 
287 // static
ConstructForwardVarargs(Isolate * isolate)288 Callable CodeFactory::ConstructForwardVarargs(Isolate* isolate) {
289   return Callable(BUILTIN_CODE(isolate, ConstructForwardVarargs),
290                   ConstructForwardVarargsDescriptor{});
291 }
292 
293 // static
ConstructFunctionForwardVarargs(Isolate * isolate)294 Callable CodeFactory::ConstructFunctionForwardVarargs(Isolate* isolate) {
295   return Callable(BUILTIN_CODE(isolate, ConstructFunctionForwardVarargs),
296                   ConstructForwardVarargsDescriptor{});
297 }
298 
299 // static
InterpreterPushArgsThenCall(Isolate * isolate,ConvertReceiverMode receiver_mode,InterpreterPushArgsMode mode)300 Callable CodeFactory::InterpreterPushArgsThenCall(
301     Isolate* isolate, ConvertReceiverMode receiver_mode,
302     InterpreterPushArgsMode mode) {
303   return Callable(
304       isolate->builtins()->InterpreterPushArgsThenCall(receiver_mode, mode),
305       InterpreterPushArgsThenCallDescriptor{});
306 }
307 
308 // static
InterpreterPushArgsThenConstruct(Isolate * isolate,InterpreterPushArgsMode mode)309 Callable CodeFactory::InterpreterPushArgsThenConstruct(
310     Isolate* isolate, InterpreterPushArgsMode mode) {
311   return Callable(isolate->builtins()->InterpreterPushArgsThenConstruct(mode),
312                   InterpreterPushArgsThenConstructDescriptor{});
313 }
314 
315 // static
InterpreterCEntry(Isolate * isolate,int result_size)316 Callable CodeFactory::InterpreterCEntry(Isolate* isolate, int result_size) {
317   // Note: If we ever use fpregs in the interpreter then we will need to
318   // save fpregs too.
319   Handle<Code> code = CodeFactory::CEntry(isolate, result_size, kDontSaveFPRegs,
320                                           kArgvInRegister);
321   if (result_size == 1) {
322     return Callable(code, InterpreterCEntry1Descriptor{});
323   } else {
324     DCHECK_EQ(result_size, 2);
325     return Callable(code, InterpreterCEntry2Descriptor{});
326   }
327 }
328 
329 // static
InterpreterOnStackReplacement(Isolate * isolate)330 Callable CodeFactory::InterpreterOnStackReplacement(Isolate* isolate) {
331   return Callable(BUILTIN_CODE(isolate, InterpreterOnStackReplacement),
332                   ContextOnlyDescriptor{});
333 }
334 
335 // static
ArrayNoArgumentConstructor(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)336 Callable CodeFactory::ArrayNoArgumentConstructor(
337     Isolate* isolate, ElementsKind kind,
338     AllocationSiteOverrideMode override_mode) {
339 #define CASE(kind_caps, kind_camel, mode_camel)                               \
340   case kind_caps:                                                             \
341     return Callable(                                                          \
342         BUILTIN_CODE(isolate,                                                 \
343                      ArrayNoArgumentConstructor_##kind_camel##_##mode_camel), \
344         ArrayNoArgumentConstructorDescriptor{})
345   if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
346     DCHECK(IsSmiElementsKind(kind));
347     switch (kind) {
348       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
349       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
350       default:
351         UNREACHABLE();
352     }
353   } else {
354     DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
355            !AllocationSite::ShouldTrack(kind));
356     switch (kind) {
357       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
358       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
359       CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
360       CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
361       CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
362       CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
363       default:
364         UNREACHABLE();
365     }
366   }
367 #undef CASE
368 }
369 
370 // static
ArraySingleArgumentConstructor(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)371 Callable CodeFactory::ArraySingleArgumentConstructor(
372     Isolate* isolate, ElementsKind kind,
373     AllocationSiteOverrideMode override_mode) {
374 #define CASE(kind_caps, kind_camel, mode_camel)                          \
375   case kind_caps:                                                        \
376     return Callable(                                                     \
377         BUILTIN_CODE(                                                    \
378             isolate,                                                     \
379             ArraySingleArgumentConstructor_##kind_camel##_##mode_camel), \
380         ArraySingleArgumentConstructorDescriptor{})
381   if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
382     DCHECK(IsSmiElementsKind(kind));
383     switch (kind) {
384       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
385       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
386       default:
387         UNREACHABLE();
388     }
389   } else {
390     DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
391            !AllocationSite::ShouldTrack(kind));
392     switch (kind) {
393       CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
394       CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
395       CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
396       CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
397       CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
398       CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
399       default:
400         UNREACHABLE();
401     }
402   }
403 #undef CASE
404 }
405 
406 // static
InternalArrayNoArgumentConstructor(Isolate * isolate,ElementsKind kind)407 Callable CodeFactory::InternalArrayNoArgumentConstructor(Isolate* isolate,
408                                                          ElementsKind kind) {
409   switch (kind) {
410     case PACKED_ELEMENTS:
411       return Callable(
412           BUILTIN_CODE(isolate, InternalArrayNoArgumentConstructor_Packed),
413           ArrayNoArgumentConstructorDescriptor{});
414     case HOLEY_ELEMENTS:
415       return Callable(
416           BUILTIN_CODE(isolate, InternalArrayNoArgumentConstructor_Holey),
417           ArrayNoArgumentConstructorDescriptor{});
418     default:
419       UNREACHABLE();
420   }
421 }
422 
423 // static
InternalArraySingleArgumentConstructor(Isolate * isolate,ElementsKind kind)424 Callable CodeFactory::InternalArraySingleArgumentConstructor(
425     Isolate* isolate, ElementsKind kind) {
426   switch (kind) {
427     case PACKED_ELEMENTS:
428       return Callable(
429           BUILTIN_CODE(isolate, InternalArraySingleArgumentConstructor_Packed),
430           ArraySingleArgumentConstructorDescriptor{});
431     case HOLEY_ELEMENTS:
432       return Callable(
433           BUILTIN_CODE(isolate, InternalArraySingleArgumentConstructor_Holey),
434           ArraySingleArgumentConstructorDescriptor{});
435     default:
436       UNREACHABLE();
437   }
438 }
439 
440 }  // namespace internal
441 }  // namespace v8
442