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