blob: 3b31399a177c46d2541ebe55e0ff31b690c30bb9 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_CODE_STUBS_H_
6#define V8_CODE_STUBS_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
9#include "src/assembler.h"
10#include "src/codegen.h"
11#include "src/globals.h"
12#include "src/ic/ic-state.h"
13#include "src/interface-descriptors.h"
14#include "src/macro-assembler.h"
15#include "src/ostreams.h"
Steve Block6ded16b2010-05-10 14:33:55 +010016
Steve Blocka7e24c12009-10-30 11:49:00 +000017namespace v8 {
18namespace internal {
19
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020// List of code stubs used on all platforms.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
22 /* PlatformCodeStubs */ \
23 V(ArgumentsAccess) \
24 V(ArrayConstructor) \
25 V(BinaryOpICWithAllocationSite) \
26 V(CallApiFunction) \
27 V(CallApiGetter) \
28 V(CallConstruct) \
29 V(CallFunction) \
30 V(CallIC) \
31 V(CallIC_Array) \
32 V(CEntry) \
33 V(CompareIC) \
34 V(DoubleToI) \
35 V(FunctionPrototype) \
36 V(Instanceof) \
37 V(InternalArrayConstructor) \
38 V(JSEntry) \
39 V(KeyedLoadICTrampoline) \
40 V(LoadICTrampoline) \
41 V(LoadIndexedInterceptor) \
42 V(MathPow) \
43 V(ProfileEntryHook) \
44 V(RecordWrite) \
45 V(RegExpExec) \
46 V(StoreArrayLiteralElement) \
47 V(StoreBufferOverflow) \
48 V(StoreElement) \
49 V(StringCompare) \
50 V(StubFailureTrampoline) \
51 V(SubString) \
52 /* HydrogenCodeStubs */ \
53 V(ArrayNArgumentsConstructor) \
54 V(ArrayNoArgumentConstructor) \
55 V(ArraySingleArgumentConstructor) \
56 V(BinaryOpIC) \
57 V(BinaryOpWithAllocationSite) \
58 V(CompareNilIC) \
59 V(CreateAllocationSite) \
60 V(ElementsTransitionAndStore) \
61 V(FastCloneShallowArray) \
62 V(FastCloneShallowObject) \
63 V(FastNewClosure) \
64 V(FastNewContext) \
65 V(InternalArrayNArgumentsConstructor) \
66 V(InternalArrayNoArgumentConstructor) \
67 V(InternalArraySingleArgumentConstructor) \
68 V(KeyedLoadGeneric) \
69 V(LoadDictionaryElement) \
70 V(LoadFastElement) \
71 V(MegamorphicLoad) \
72 V(NameDictionaryLookup) \
73 V(NumberToString) \
74 V(RegExpConstructResult) \
75 V(StoreFastElement) \
76 V(StringAdd) \
77 V(ToBoolean) \
78 V(ToNumber) \
79 V(TransitionElementsKind) \
80 V(VectorKeyedLoad) \
81 V(VectorLoad) \
82 /* IC Handler stubs */ \
83 V(LoadConstant) \
84 V(LoadField) \
85 V(KeyedLoadSloppyArguments) \
86 V(StoreField) \
87 V(StoreGlobal) \
88 V(StringLength)
Steve Blockd0582a62009-12-15 09:54:21 +000089
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090// List of code stubs only used on ARM 32 bits platforms.
91#if V8_TARGET_ARCH_ARM
92#define CODE_STUB_LIST_ARM(V) \
93 V(DirectCEntry) \
94 V(WriteInt32ToHeapNumber)
95
Steve Blockd0582a62009-12-15 09:54:21 +000096#else
97#define CODE_STUB_LIST_ARM(V)
98#endif
99
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100// List of code stubs only used on ARM 64 bits platforms.
101#if V8_TARGET_ARCH_ARM64
102#define CODE_STUB_LIST_ARM64(V) \
103 V(DirectCEntry) \
104 V(RestoreRegistersState) \
105 V(StoreRegistersState)
106
107#else
108#define CODE_STUB_LIST_ARM64(V)
109#endif
110
Steve Block44f0eee2011-05-26 01:26:41 +0100111// List of code stubs only used on MIPS platforms.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112#if V8_TARGET_ARCH_MIPS
Steve Block44f0eee2011-05-26 01:26:41 +0100113#define CODE_STUB_LIST_MIPS(V) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 V(DirectCEntry) \
115 V(RestoreRegistersState) \
116 V(StoreRegistersState) \
117 V(WriteInt32ToHeapNumber)
118#elif V8_TARGET_ARCH_MIPS64
119#define CODE_STUB_LIST_MIPS(V) \
120 V(DirectCEntry) \
121 V(RestoreRegistersState) \
122 V(StoreRegistersState) \
123 V(WriteInt32ToHeapNumber)
Steve Block44f0eee2011-05-26 01:26:41 +0100124#else
125#define CODE_STUB_LIST_MIPS(V)
126#endif
127
Steve Blockd0582a62009-12-15 09:54:21 +0000128// Combined list of code stubs.
129#define CODE_STUB_LIST(V) \
130 CODE_STUB_LIST_ALL_PLATFORMS(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100131 CODE_STUB_LIST_ARM(V) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132 CODE_STUB_LIST_ARM64(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100133 CODE_STUB_LIST_MIPS(V)
Steve Blocka7e24c12009-10-30 11:49:00 +0000134
135// Stub is base classes of all stubs.
136class CodeStub BASE_EMBEDDED {
137 public:
138 enum Major {
Steve Blockd0582a62009-12-15 09:54:21 +0000139#define DEF_ENUM(name) name,
140 CODE_STUB_LIST(DEF_ENUM)
141#undef DEF_ENUM
142 NoCache, // marker for stubs that do custom caching
Steve Blocka7e24c12009-10-30 11:49:00 +0000143 NUMBER_OF_IDS
144 };
145
146 // Retrieve the code for the stub. Generate the code if needed.
147 Handle<Code> GetCode();
148
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 // Retrieve the code for the stub, make and return a copy of the code.
150 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
151
Steve Blocka7e24c12009-10-30 11:49:00 +0000152 static Major MajorKeyFromKey(uint32_t key) {
153 return static_cast<Major>(MajorKeyBits::decode(key));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100154 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155 static uint32_t MinorKeyFromKey(uint32_t key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 return MinorKeyBits::decode(key);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100157 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100158
159 // Gets the major key from a code object that is a code stub or binary op IC.
160 static Major GetMajorKey(Code* code_stub) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 return MajorKeyFromKey(code_stub->stub_key());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100162 }
163
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
165
Andrei Popescu31002712010-02-23 13:46:05 +0000166 static const char* MajorName(Major major_key, bool allow_unknown_keys);
Steve Blocka7e24c12009-10-30 11:49:00 +0000167
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 virtual ~CodeStub() {}
170
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 static void GenerateStubsAheadOfTime(Isolate* isolate);
172 static void GenerateFPStubs(Isolate* isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100173
174 // Some stubs put untagged junk on the stack that cannot be scanned by the
175 // GC. This means that we must be statically sure that no GC can occur while
176 // they are running. If that is the case they should override this to return
177 // true, which will cause an assertion if we try to call something that can
178 // GC or if we try to put a stack frame on top of the junk, which would not
179 // result in a traversable stack.
180 virtual bool SometimesSetsUpAFrame() { return true; }
181
182 // Lookup the code in the (possibly custom) cache.
183 bool FindCodeInCache(Code** code_out);
184
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000186
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
188
189 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
190 CodeStubDescriptor* desc);
191
192 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
193
194 // Returns information for computing the number key.
195 virtual Major MajorKey() const = 0;
196 uint32_t MinorKey() const { return minor_key_; }
197
198 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
199 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
200 virtual Code::StubType GetStubType() {
201 return Code::NORMAL;
202 }
203
204 friend OStream& operator<<(OStream& os, const CodeStub& s) {
205 s.PrintName(os);
206 return os;
207 }
208
209 Isolate* isolate() const { return isolate_; }
210
211 protected:
212 CodeStub(uint32_t key, Isolate* isolate)
213 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
Leon Clarkee46be812010-01-19 14:06:41 +0000214
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 // Generates the assembler code for the stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 virtual Handle<Code> GenerateCode() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 // Returns whether the code generated for this stub needs to be allocated as
219 // a fixed (non-moveable) code object.
220 virtual bool NeedsImmovableCode() { return false; }
221
222 virtual void PrintName(OStream& os) const; // NOLINT
223 virtual void PrintBaseName(OStream& os) const; // NOLINT
224 virtual void PrintState(OStream& os) const { ; } // NOLINT
225
226 // Computes the key based on major and minor.
227 uint32_t GetKey() {
228 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
229 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
230 }
231
232 uint32_t minor_key_;
233
234 private:
Leon Clarkee46be812010-01-19 14:06:41 +0000235 // Perform bookkeeping required after code generation when stub code is
236 // initially generated.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 void RecordCodeGeneration(Handle<Code> code);
Leon Clarkee46be812010-01-19 14:06:41 +0000238
Ben Murdochb0fe1622011-05-05 13:52:32 +0100239 // Finish the code object after it has been generated.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100240 virtual void FinishCode(Handle<Code> code) { }
241
242 // Activate newly generated stub. Is called after
243 // registering stub in the stub cache.
244 virtual void Activate(Code* code) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100245
Ben Murdoch257744e2011-11-30 15:57:28 +0000246 // BinaryOpStub needs to override this.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 virtual Code::Kind GetCodeKind() const;
Steve Block6ded16b2010-05-10 14:33:55 +0100248
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100249 // Add the code to a specialized cache, specific to an individual
250 // stub type. Please note, this method must add the code object to a
251 // roots object, otherwise we will remove the code during GC.
252 virtual void AddToSpecialCache(Handle<Code> new_object) { }
253
254 // Find code in a specialized cache, work is delegated to the specific stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 virtual bool FindCodeInSpecialCache(Code** code_out) {
256 return false;
257 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100258
259 // If a stub uses a special cache override this.
260 virtual bool UseSpecialCache() { return false; }
261
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 // We use this dispatch to statically instantiate the correct code stub for
263 // the given stub key and call the passed function with that code stub.
264 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
265 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
266 DispatchedCall call);
Steve Blocka7e24c12009-10-30 11:49:00 +0000267
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
Steve Block44f0eee2011-05-26 01:26:41 +0100269
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000270 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
271 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
272 class MinorKeyBits: public BitField<uint32_t,
273 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000274
275 friend class BreakPointIterator;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276
277 Isolate* isolate_;
278};
279
280
281#define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
282 public: \
283 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
284 \
285 private: \
286 DISALLOW_COPY_AND_ASSIGN(NAME)
287
288
289#define DEFINE_CODE_STUB(NAME, SUPER) \
290 protected: \
291 virtual inline Major MajorKey() const OVERRIDE { \
292 return NAME; \
293 }; \
294 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
295
296
297#define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
298 private: \
299 virtual void Generate(MacroAssembler* masm) OVERRIDE; \
300 DEFINE_CODE_STUB(NAME, SUPER)
301
302
303#define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
304 public: \
305 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE; \
306 virtual Handle<Code> GenerateCode() OVERRIDE; \
307 DEFINE_CODE_STUB(NAME, SUPER)
308
309#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
310 public: \
311 virtual Handle<Code> GenerateCode() OVERRIDE; \
312 DEFINE_CODE_STUB(NAME, SUPER)
313
314#define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
315 public: \
316 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
317 return NAME##Descriptor(isolate()); \
318 }
319
320// There are some code stubs we just can't describe right now with a
321// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
322// An attempt to retrieve a descriptor will fail.
323#define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
324 public: \
325 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
326 UNREACHABLE(); \
327 return CallInterfaceDescriptor(); \
328 }
329
330
331class PlatformCodeStub : public CodeStub {
332 public:
333 // Retrieve the code for the stub. Generate the code if needed.
334 virtual Handle<Code> GenerateCode() OVERRIDE;
335
336 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
337
338 protected:
339 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
340
341 // Generates the assembler code for the stub.
342 virtual void Generate(MacroAssembler* masm) = 0;
343
344 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
345};
346
347
348enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
349enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
350
351
352class CodeStubDescriptor {
353 public:
354 explicit CodeStubDescriptor(CodeStub* stub);
355
356 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
357
358 void Initialize(Address deoptimization_handler = NULL,
359 int hint_stack_parameter_count = -1,
360 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
361 void Initialize(Register stack_parameter_count,
362 Address deoptimization_handler = NULL,
363 int hint_stack_parameter_count = -1,
364 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
365 HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
366
367 void SetMissHandler(ExternalReference handler) {
368 miss_handler_ = handler;
369 has_miss_handler_ = true;
370 // Our miss handler infrastructure doesn't currently support
371 // variable stack parameter counts.
372 DCHECK(!stack_parameter_count_.is_valid());
373 }
374
375 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
376 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
377
378 int GetEnvironmentParameterCount() const {
379 return call_descriptor().GetEnvironmentParameterCount();
380 }
381
382 Representation GetEnvironmentParameterRepresentation(int index) const {
383 return call_descriptor().GetEnvironmentParameterRepresentation(index);
384 }
385
386 ExternalReference miss_handler() const {
387 DCHECK(has_miss_handler_);
388 return miss_handler_;
389 }
390
391 bool has_miss_handler() const {
392 return has_miss_handler_;
393 }
394
395 bool IsEnvironmentParameterCountRegister(int index) const {
396 return call_descriptor().GetEnvironmentParameterRegister(index).is(
397 stack_parameter_count_);
398 }
399
400 int GetHandlerParameterCount() const {
401 int params = call_descriptor().GetEnvironmentParameterCount();
402 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
403 params += 1;
404 }
405 return params;
406 }
407
408 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
409 Register stack_parameter_count() const { return stack_parameter_count_; }
410 StubFunctionMode function_mode() const { return function_mode_; }
411 Address deoptimization_handler() const { return deoptimization_handler_; }
412
413 private:
414 CallInterfaceDescriptor call_descriptor_;
415 Register stack_parameter_count_;
416 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
417 // return sequence. Default value is -1, which means it is ignored.
418 int hint_stack_parameter_count_;
419 StubFunctionMode function_mode_;
420
421 Address deoptimization_handler_;
422 HandlerArgumentsMode handler_arguments_mode_;
423
424 ExternalReference miss_handler_;
425 bool has_miss_handler_;
426};
427
428
429class HydrogenCodeStub : public CodeStub {
430 public:
431 enum InitializationState {
432 UNINITIALIZED,
433 INITIALIZED
434 };
435
436 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
437
438 template<class SubClass>
439 static Handle<Code> GetUninitialized(Isolate* isolate) {
440 SubClass::GenerateAheadOfTime(isolate);
441 return SubClass().GetCode(isolate);
442 }
443
444 // Retrieve the code for the stub. Generate the code if needed.
445 virtual Handle<Code> GenerateCode() = 0;
446
447 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
448
449 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
450
451 template<class StateType>
452 void TraceTransition(StateType from, StateType to);
453
454 protected:
455 explicit HydrogenCodeStub(Isolate* isolate,
456 InitializationState state = INITIALIZED)
457 : CodeStub(isolate) {
458 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
459 }
460
461 void set_sub_minor_key(uint32_t key) {
462 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
463 }
464
465 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
466
467 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
468
469 private:
470 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
471 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
472
473 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
474
475 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000476};
477
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100478
479// Helper interface to prepare to/restore after making runtime calls.
480class RuntimeCallHelper {
481 public:
482 virtual ~RuntimeCallHelper() {}
483
484 virtual void BeforeCall(MacroAssembler* masm) const = 0;
485
486 virtual void AfterCall(MacroAssembler* masm) const = 0;
487
488 protected:
489 RuntimeCallHelper() {}
490
491 private:
492 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
493};
494
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100496} } // namespace v8::internal
497
498#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499#include "src/ia32/code-stubs-ia32.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100500#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501#include "src/x64/code-stubs-x64.h"
502#elif V8_TARGET_ARCH_ARM64
503#include "src/arm64/code-stubs-arm64.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100504#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505#include "src/arm/code-stubs-arm.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100506#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507#include "src/mips/code-stubs-mips.h"
508#elif V8_TARGET_ARCH_MIPS64
509#include "src/mips64/code-stubs-mips64.h"
510#elif V8_TARGET_ARCH_X87
511#include "src/x87/code-stubs-x87.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100512#else
513#error Unsupported target architecture.
514#endif
515
516namespace v8 {
517namespace internal {
518
519
Ben Murdochb0fe1622011-05-05 13:52:32 +0100520// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100521// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100522class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100523 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100524 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100525
526 virtual void BeforeCall(MacroAssembler* masm) const;
527
528 virtual void AfterCall(MacroAssembler* masm) const;
529};
530
531
532// Trivial RuntimeCallHelper implementation.
533class NopRuntimeCallHelper : public RuntimeCallHelper {
534 public:
535 NopRuntimeCallHelper() {}
536
537 virtual void BeforeCall(MacroAssembler* masm) const {}
538
539 virtual void AfterCall(MacroAssembler* masm) const {}
540};
541
542
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543class ToNumberStub: public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100544 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100546
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
548 DEFINE_HYDROGEN_CODE_STUB(ToNumber, HydrogenCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100549};
550
551
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552class NumberToStringStub FINAL : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100553 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100555
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
557 static const int kNumber = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100558
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
560 DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100561};
562
563
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564class FastNewClosureStub : public HydrogenCodeStub {
Steve Block1e0659c2011-05-24 12:43:12 +0100565 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
567 FunctionKind kind)
568 : HydrogenCodeStub(isolate) {
569 DCHECK(IsValidFunctionKind(kind));
570 set_sub_minor_key(StrictModeBits::encode(strict_mode) |
571 FunctionKindBits::encode(kind));
572 }
Steve Block1e0659c2011-05-24 12:43:12 +0100573
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000574 StrictMode strict_mode() const {
575 return StrictModeBits::decode(sub_minor_key());
576 }
577
578 FunctionKind kind() const {
579 return FunctionKindBits::decode(sub_minor_key());
580 }
581 bool is_arrow() const { return IsArrowFunction(kind()); }
582 bool is_generator() const { return IsGeneratorFunction(kind()); }
583 bool is_concise_method() const { return IsConciseMethod(kind()); }
Steve Block1e0659c2011-05-24 12:43:12 +0100584
585 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 class StrictModeBits : public BitField<StrictMode, 0, 1> {};
587 class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
588
589 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
590 DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
Steve Block1e0659c2011-05-24 12:43:12 +0100591};
592
593
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594class FastNewContextStub FINAL : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100595 public:
596 static const int kMaximumSlots = 64;
597
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
599 DCHECK(slots > 0 && slots <= kMaximumSlots);
600 set_sub_minor_key(SlotsBits::encode(slots));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100601 }
602
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 int slots() const { return SlotsBits::decode(sub_minor_key()); }
604
605 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
606 static const int kFunction = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100607
608 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 class SlotsBits : public BitField<int, 0, 8> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100610
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
612 DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100613};
614
615
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616class FastCloneShallowArrayStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100617 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 FastCloneShallowArrayStub(Isolate* isolate,
619 AllocationSiteMode allocation_site_mode)
620 : HydrogenCodeStub(isolate) {
621 set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100622 }
623
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 AllocationSiteMode allocation_site_mode() const {
625 return AllocationSiteModeBits::decode(sub_minor_key());
626 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100627
628 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100630
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
632 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100633};
634
635
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636class FastCloneShallowObjectStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100637 public:
638 // Maximum number of properties in copied object.
639 static const int kMaximumClonedProperties = 6;
640
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 FastCloneShallowObjectStub(Isolate* isolate, int length)
642 : HydrogenCodeStub(isolate) {
643 DCHECK_GE(length, 0);
644 DCHECK_LE(length, kMaximumClonedProperties);
645 set_sub_minor_key(LengthBits::encode(length));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100646 }
647
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 int length() const { return LengthBits::decode(sub_minor_key()); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100649
650 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651 class LengthBits : public BitField<int, 0, 4> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100652
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
654 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100655};
656
657
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658class CreateAllocationSiteStub : public HydrogenCodeStub {
659 public:
660 explicit CreateAllocationSiteStub(Isolate* isolate)
661 : HydrogenCodeStub(isolate) { }
662
663 static void GenerateAheadOfTime(Isolate* isolate);
664
665 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
666 DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
667};
668
669
670class InstanceofStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100671 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 enum Flags {
673 kNoFlags = 0,
Ben Murdoch086aeea2011-05-13 15:57:08 +0100674 kArgsInRegisters = 1 << 0,
675 kCallSiteInlineCheck = 1 << 1,
676 kReturnTrueFalseObject = 1 << 2
Ben Murdochb0fe1622011-05-05 13:52:32 +0100677 };
678
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 InstanceofStub(Isolate* isolate, Flags flags) : PlatformCodeStub(isolate) {
680 minor_key_ = FlagBits::encode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100681 }
682
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 static Register left() { return InstanceofDescriptor::left(); }
684 static Register right() { return InstanceofDescriptor::right(); }
685
686 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
687 if (HasArgsInRegisters()) {
688 return InstanceofDescriptor(isolate());
689 }
690 return ContextOnlyDescriptor(isolate());
691 }
692
693 private:
694 Flags flags() const { return FlagBits::decode(minor_key_); }
695
696 bool HasArgsInRegisters() const { return (flags() & kArgsInRegisters) != 0; }
697
Ben Murdoch086aeea2011-05-13 15:57:08 +0100698 bool HasCallSiteInlineCheck() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 return (flags() & kCallSiteInlineCheck) != 0;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100700 }
701
702 bool ReturnTrueFalseObject() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 return (flags() & kReturnTrueFalseObject) != 0;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100704 }
705
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
Ben Murdoch086aeea2011-05-13 15:57:08 +0100707
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 class FlagBits : public BitField<Flags, 0, 3> {};
709
710 DEFINE_PLATFORM_CODE_STUB(Instanceof, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100711};
712
713
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714enum AllocationSiteOverrideMode {
715 DONT_OVERRIDE,
716 DISABLE_ALLOCATION_SITES,
717 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
718};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100719
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720
721class ArrayConstructorStub: public PlatformCodeStub {
722 public:
723 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
724
725 ArrayConstructorStub(Isolate* isolate, int argument_count);
726
727 explicit ArrayConstructorStub(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100728
729 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000730 ArgumentCountKey argument_count() const {
731 return ArgumentCountBits::decode(minor_key_);
732 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100733
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000734 void GenerateDispatchToArrayStub(MacroAssembler* masm,
735 AllocationSiteOverrideMode mode);
736
737 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
738
739 class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
740
741 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
742 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100743};
744
745
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746class InternalArrayConstructorStub: public PlatformCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100747 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 explicit InternalArrayConstructorStub(Isolate* isolate);
749
750 private:
751 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
752
753 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
754 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
755};
756
757
758class MathPowStub: public PlatformCodeStub {
759 public:
760 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
761
762 MathPowStub(Isolate* isolate, ExponentType exponent_type)
763 : PlatformCodeStub(isolate) {
764 minor_key_ = ExponentTypeBits::encode(exponent_type);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100765 }
766
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
768 if (exponent_type() == TAGGED) {
769 return MathPowTaggedDescriptor(isolate());
770 } else if (exponent_type() == INTEGER) {
771 return MathPowIntegerDescriptor(isolate());
772 }
773 // A CallInterfaceDescriptor doesn't specify double registers (yet).
774 return ContextOnlyDescriptor(isolate());
775 }
776
777 private:
778 ExponentType exponent_type() const {
779 return ExponentTypeBits::decode(minor_key_);
780 }
781
782 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
783
784 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
785};
786
787
788class CallICStub: public PlatformCodeStub {
789 public:
790 CallICStub(Isolate* isolate, const CallICState& state)
791 : PlatformCodeStub(isolate) {
792 minor_key_ = state.GetExtraICState();
793 }
794
795 static int ExtractArgcFromMinorKey(int minor_key) {
796 CallICState state(static_cast<ExtraICState>(minor_key));
797 return state.arg_count();
798 }
799
800 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::CALL_IC; }
801
802 virtual InlineCacheState GetICState() const OVERRIDE { return DEFAULT; }
803
804 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
805 return static_cast<ExtraICState>(minor_key_);
806 }
807
808 protected:
809 bool CallAsMethod() const {
810 return state().call_type() == CallICState::METHOD;
811 }
812
813 int arg_count() const { return state().arg_count(); }
814
815 CallICState state() const {
816 return CallICState(static_cast<ExtraICState>(minor_key_));
817 }
818
819 // Code generation helpers.
820 void GenerateMiss(MacroAssembler* masm);
821
822 private:
823 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
824
825 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
826 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
827};
828
829
830class CallIC_ArrayStub: public CallICStub {
831 public:
832 CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
833 : CallICStub(isolate, state_in) {}
834
835 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
836 return MONOMORPHIC;
837 }
838
839 private:
840 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
841
842 DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
843};
844
845
846// TODO(verwaest): Translate to hydrogen code stub.
847class FunctionPrototypeStub : public PlatformCodeStub {
848 public:
849 explicit FunctionPrototypeStub(Isolate* isolate)
850 : PlatformCodeStub(isolate) {}
851
852 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
853
854 // TODO(mvstanton): only the receiver register is accessed. When this is
855 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
856 // should be created that just uses that register for more efficient code.
857 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
858 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
859};
860
861
862// TODO(mvstanton): Translate to hydrogen code stub.
863class LoadIndexedInterceptorStub : public PlatformCodeStub {
864 public:
865 explicit LoadIndexedInterceptorStub(Isolate* isolate)
866 : PlatformCodeStub(isolate) {}
867
868 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
869 virtual Code::StubType GetStubType() { return Code::FAST; }
870
871 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
872 DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
873};
874
875
876class HandlerStub : public HydrogenCodeStub {
877 public:
878 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
879 virtual ExtraICState GetExtraICState() const { return kind(); }
880 virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
881
882 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE;
883
884 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
885
886 protected:
887 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
888
889 virtual Code::Kind kind() const = 0;
890
891 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
892};
893
894
895class LoadFieldStub: public HandlerStub {
896 public:
897 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
898 int property_index_key = index.GetFieldAccessStubKey();
899 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
900 }
901
902 FieldIndex index() const {
903 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
904 return FieldIndex::FromFieldAccessStubKey(property_index_key);
905 }
906
907 protected:
908 virtual Code::Kind kind() const { return Code::LOAD_IC; }
909 virtual Code::StubType GetStubType() { return Code::FAST; }
910
911 private:
912 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
913
914 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
915};
916
917
918class KeyedLoadSloppyArgumentsStub : public HandlerStub {
919 public:
920 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
921 : HandlerStub(isolate) {}
922
923 protected:
924 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
925 virtual Code::StubType GetStubType() { return Code::FAST; }
926
927 private:
928 DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
929};
930
931
932class LoadConstantStub : public HandlerStub {
933 public:
934 LoadConstantStub(Isolate* isolate, int constant_index)
935 : HandlerStub(isolate) {
936 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
937 }
938
939 int constant_index() const {
940 return ConstantIndexBits::decode(sub_minor_key());
941 }
942
943 protected:
944 virtual Code::Kind kind() const { return Code::LOAD_IC; }
945 virtual Code::StubType GetStubType() { return Code::FAST; }
946
947 private:
948 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
949
950 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
951};
952
953
954class StringLengthStub: public HandlerStub {
955 public:
956 explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
957
958 protected:
959 virtual Code::Kind kind() const { return Code::LOAD_IC; }
960 virtual Code::StubType GetStubType() { return Code::FAST; }
961
962 DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
963};
964
965
966class StoreFieldStub : public HandlerStub {
967 public:
968 StoreFieldStub(Isolate* isolate, FieldIndex index,
969 Representation representation)
970 : HandlerStub(isolate) {
971 int property_index_key = index.GetFieldAccessStubKey();
972 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
973 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
974 RepresentationBits::encode(repr));
975 }
976
977 FieldIndex index() const {
978 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
979 return FieldIndex::FromFieldAccessStubKey(property_index_key);
980 }
981
982 Representation representation() {
983 uint8_t repr = RepresentationBits::decode(sub_minor_key());
984 return PropertyDetails::DecodeRepresentation(repr);
985 }
986
987 protected:
988 virtual Code::Kind kind() const { return Code::STORE_IC; }
989 virtual Code::StubType GetStubType() { return Code::FAST; }
990
991 private:
992 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
993 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
994
995 DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
996};
997
998
999class StoreGlobalStub : public HandlerStub {
1000 public:
1001 StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1002 : HandlerStub(isolate) {
1003 set_sub_minor_key(IsConstantBits::encode(is_constant) |
1004 CheckGlobalBits::encode(check_global));
1005 }
1006
1007 static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1008 return isolate->factory()->uninitialized_value();
1009 }
1010
1011 Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1012 Handle<PropertyCell> cell) {
1013 if (check_global()) {
1014 Code::FindAndReplacePattern pattern;
1015 pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1016 pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1017 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1018 return CodeStub::GetCodeCopy(pattern);
1019 } else {
1020 Code::FindAndReplacePattern pattern;
1021 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1022 return CodeStub::GetCodeCopy(pattern);
1023 }
1024 }
1025
1026 virtual Code::Kind kind() const { return Code::STORE_IC; }
1027
1028 bool is_constant() const { return IsConstantBits::decode(sub_minor_key()); }
1029
1030 bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1031
1032 void set_is_constant(bool value) {
1033 set_sub_minor_key(IsConstantBits::update(sub_minor_key(), value));
1034 }
1035
1036 Representation representation() {
1037 return Representation::FromKind(
1038 RepresentationBits::decode(sub_minor_key()));
1039 }
1040
1041 void set_representation(Representation r) {
1042 set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1043 }
1044
1045 private:
1046 class IsConstantBits: public BitField<bool, 0, 1> {};
1047 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1048 class CheckGlobalBits: public BitField<bool, 9, 1> {};
1049
1050 DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1051};
1052
1053
1054class CallApiFunctionStub : public PlatformCodeStub {
1055 public:
1056 CallApiFunctionStub(Isolate* isolate,
1057 bool is_store,
1058 bool call_data_undefined,
1059 int argc) : PlatformCodeStub(isolate) {
1060 minor_key_ = IsStoreBits::encode(is_store) |
1061 CallDataUndefinedBits::encode(call_data_undefined) |
1062 ArgumentBits::encode(argc);
1063 DCHECK(!is_store || argc == 1);
1064 }
1065
1066 private:
1067 bool is_store() const { return IsStoreBits::decode(minor_key_); }
1068 bool call_data_undefined() const {
1069 return CallDataUndefinedBits::decode(minor_key_);
1070 }
1071 int argc() const { return ArgumentBits::decode(minor_key_); }
1072
1073 class IsStoreBits: public BitField<bool, 0, 1> {};
1074 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1075 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1076 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1077
1078 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1079 DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1080};
1081
1082
1083class CallApiGetterStub : public PlatformCodeStub {
1084 public:
1085 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1086
1087 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1088 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1089};
1090
1091
1092class BinaryOpICStub : public HydrogenCodeStub {
1093 public:
1094 BinaryOpICStub(Isolate* isolate, Token::Value op,
1095 OverwriteMode mode = NO_OVERWRITE)
1096 : HydrogenCodeStub(isolate, UNINITIALIZED) {
1097 BinaryOpICState state(isolate, op, mode);
1098 set_sub_minor_key(state.GetExtraICState());
1099 }
1100
1101 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1102 : HydrogenCodeStub(isolate) {
1103 set_sub_minor_key(state.GetExtraICState());
1104 }
1105
1106 static void GenerateAheadOfTime(Isolate* isolate);
1107
1108 virtual Code::Kind GetCodeKind() const OVERRIDE {
1109 return Code::BINARY_OP_IC;
1110 }
1111
1112 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1113 return state().GetICState();
1114 }
1115
1116 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1117 return static_cast<ExtraICState>(sub_minor_key());
1118 }
1119
1120 BinaryOpICState state() const {
1121 return BinaryOpICState(isolate(), GetExtraICState());
1122 }
1123
1124 virtual void PrintState(OStream& os) const FINAL OVERRIDE; // NOLINT
1125
1126 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1127 static const int kLeft = 0;
1128 static const int kRight = 1;
1129
1130 private:
1131 static void GenerateAheadOfTime(Isolate* isolate,
1132 const BinaryOpICState& state);
1133
1134 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1135 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1136};
1137
1138
1139// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1140// call support for stubs in Hydrogen.
1141class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub {
1142 public:
1143 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1144 const BinaryOpICState& state)
1145 : PlatformCodeStub(isolate) {
1146 minor_key_ = state.GetExtraICState();
1147 }
1148
1149 static void GenerateAheadOfTime(Isolate* isolate);
1150
1151 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1152 Code::FindAndReplacePattern pattern;
1153 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1154 return CodeStub::GetCodeCopy(pattern);
1155 }
1156
1157 virtual Code::Kind GetCodeKind() const OVERRIDE {
1158 return Code::BINARY_OP_IC;
1159 }
1160
1161 virtual InlineCacheState GetICState() const OVERRIDE {
1162 return state().GetICState();
1163 }
1164
1165 virtual ExtraICState GetExtraICState() const OVERRIDE {
1166 return static_cast<ExtraICState>(minor_key_);
1167 }
1168
1169 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
1170
1171 private:
1172 BinaryOpICState state() const {
1173 return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1174 }
1175
1176 static void GenerateAheadOfTime(Isolate* isolate,
1177 const BinaryOpICState& state);
1178
1179 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1180 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1181};
1182
1183
1184class BinaryOpWithAllocationSiteStub FINAL : public BinaryOpICStub {
1185 public:
1186 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1187 Token::Value op,
1188 OverwriteMode mode)
1189 : BinaryOpICStub(isolate, op, mode) {}
1190
1191 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1192 : BinaryOpICStub(isolate, state) {}
1193
1194 virtual Code::Kind GetCodeKind() const FINAL OVERRIDE {
1195 return Code::STUB;
1196 }
1197
1198 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1199 static const int kAllocationSite = 0;
1200 static const int kLeft = 1;
1201 static const int kRight = 2;
1202
1203 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1204 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1205};
1206
1207
1208enum StringAddFlags {
1209 // Omit both parameter checks.
1210 STRING_ADD_CHECK_NONE = 0,
1211 // Check left parameter.
1212 STRING_ADD_CHECK_LEFT = 1 << 0,
1213 // Check right parameter.
1214 STRING_ADD_CHECK_RIGHT = 1 << 1,
1215 // Check both parameters.
1216 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1217};
1218
1219
1220class StringAddStub FINAL : public HydrogenCodeStub {
1221 public:
1222 StringAddStub(Isolate* isolate, StringAddFlags flags,
1223 PretenureFlag pretenure_flag)
1224 : HydrogenCodeStub(isolate) {
1225 set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1226 PretenureFlagBits::encode(pretenure_flag));
1227 }
1228
1229 StringAddFlags flags() const {
1230 return StringAddFlagsBits::decode(sub_minor_key());
1231 }
1232
1233 PretenureFlag pretenure_flag() const {
1234 return PretenureFlagBits::decode(sub_minor_key());
1235 }
1236
1237 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1238 static const int kLeft = 0;
1239 static const int kRight = 1;
1240
1241 private:
1242 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1243 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1244
1245 virtual void PrintBaseName(OStream& os) const OVERRIDE; // NOLINT
1246
1247 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1248 DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1249};
1250
1251
1252class CompareICStub : public PlatformCodeStub {
1253 public:
1254 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1255 CompareICState::State right, CompareICState::State state)
1256 : PlatformCodeStub(isolate) {
1257 DCHECK(Token::IsCompareOp(op));
1258 minor_key_ = OpBits::encode(op - Token::EQ) | LeftStateBits::encode(left) |
1259 RightStateBits::encode(right) | StateBits::encode(state);
1260 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001261
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001262 void set_known_map(Handle<Map> map) { known_map_ = map; }
1263
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 virtual InlineCacheState GetICState() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001265
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 Token::Value op() const {
1267 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001268 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001269
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270 CompareICState::State left() const {
1271 return LeftStateBits::decode(minor_key_);
1272 }
1273 CompareICState::State right() const {
1274 return RightStateBits::decode(minor_key_);
1275 }
1276 CompareICState::State state() const { return StateBits::decode(minor_key_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001277
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001278 private:
1279 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001280
1281 void GenerateSmis(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 void GenerateNumbers(MacroAssembler* masm);
1283 void GenerateInternalizedStrings(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00001284 void GenerateStrings(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 void GenerateUniqueNames(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001286 void GenerateObjects(MacroAssembler* masm);
1287 void GenerateMiss(MacroAssembler* masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001288 void GenerateKnownObjects(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 void GenerateGeneric(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001290
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 bool strict() const { return op() == Token::EQ_STRICT; }
1292 Condition GetCondition() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001293
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001294 virtual void AddToSpecialCache(Handle<Code> new_object);
1295 virtual bool FindCodeInSpecialCache(Code** code_out);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296 virtual bool UseSpecialCache() {
1297 return state() == CompareICState::KNOWN_OBJECT;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001298 }
1299
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300 class OpBits : public BitField<int, 0, 3> {};
1301 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1302 class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1303 class StateBits : public BitField<CompareICState::State, 11, 4> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001304
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 Handle<Map> known_map_;
1306
1307 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1308 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001309};
1310
1311
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312class CompareNilICStub : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001313 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1315 Type* GetInputType(Zone* zone, Handle<Map> map);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001316
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1318 set_sub_minor_key(NilValueBits::encode(nil));
1319 }
1320
1321 CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1322 InitializationState init_state = INITIALIZED)
1323 : HydrogenCodeStub(isolate, init_state) {
1324 set_sub_minor_key(ic_state);
1325 }
1326
1327 static Handle<Code> GetUninitialized(Isolate* isolate,
1328 NilValue nil) {
1329 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1330 }
1331
1332 virtual InlineCacheState GetICState() const {
1333 State state = this->state();
1334 if (state.Contains(GENERIC)) {
1335 return MEGAMORPHIC;
1336 } else if (state.Contains(MONOMORPHIC_MAP)) {
1337 return MONOMORPHIC;
1338 } else {
1339 return PREMONOMORPHIC;
1340 }
1341 }
1342
1343 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1344
1345 virtual ExtraICState GetExtraICState() const { return sub_minor_key(); }
1346
1347 void UpdateStatus(Handle<Object> object);
1348
1349 bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1350
1351 NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1352
1353 void ClearState() {
1354 set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1355 }
1356
1357 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
1358 virtual void PrintBaseName(OStream& os) const OVERRIDE; // NOLINT
1359
1360 private:
1361 CompareNilICStub(Isolate* isolate, NilValue nil,
1362 InitializationState init_state)
1363 : HydrogenCodeStub(isolate, init_state) {
1364 set_sub_minor_key(NilValueBits::encode(nil));
1365 }
1366
1367 enum CompareNilType {
1368 UNDEFINED,
1369 NULL_TYPE,
1370 MONOMORPHIC_MAP,
1371 GENERIC,
1372 NUMBER_OF_TYPES
1373 };
1374
1375 // At most 6 different types can be distinguished, because the Code object
1376 // only has room for a single byte to hold a set and there are two more
1377 // boolean flags we need to store. :-P
1378 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1379
1380 class State : public EnumSet<CompareNilType, byte> {
1381 public:
1382 State() : EnumSet<CompareNilType, byte>(0) { }
1383 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1384 };
1385 friend OStream& operator<<(OStream& os, const State& s);
1386
1387 State state() const { return State(TypesBits::decode(sub_minor_key())); }
1388
1389 class NilValueBits : public BitField<NilValue, 0, 1> {};
1390 class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1391
1392 friend class CompareNilIC;
1393
1394 DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1395 DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1396};
1397
1398
1399OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1400
1401
1402class CEntryStub : public PlatformCodeStub {
1403 public:
1404 CEntryStub(Isolate* isolate, int result_size,
1405 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1406 : PlatformCodeStub(isolate) {
1407 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1408 DCHECK(result_size == 1 || result_size == 2);
1409#ifdef _WIN64
1410 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1411#endif // _WIN64
1412 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001413
1414 // The version of this stub that doesn't save doubles is generated ahead of
1415 // time, so it's OK to call it from other stubs that can't cope with GC during
1416 // their code generation. On machines that always have gp registers (x64) we
1417 // can generate both variants ahead of time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418 static void GenerateAheadOfTime(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001419
1420 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1422#ifdef _WIN64
1423 int result_size() const { return ResultSizeBits::decode(minor_key_); }
1424#endif // _WIN64
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001425
Steve Block44f0eee2011-05-26 01:26:41 +01001426 bool NeedsImmovableCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427
1428 class SaveDoublesBits : public BitField<bool, 0, 1> {};
1429 class ResultSizeBits : public BitField<int, 1, 3> {};
1430
1431 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1432 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001433};
1434
1435
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436class JSEntryStub : public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001437 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001438 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1439 : PlatformCodeStub(isolate) {
1440 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1441 minor_key_ = StackFrameTypeBits::encode(type);
1442 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001443
1444 private:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001445 virtual void FinishCode(Handle<Code> code);
1446
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001447 virtual void PrintName(OStream& os) const OVERRIDE { // NOLINT
1448 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1449 : "JSConstructEntryStub");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001450 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451
1452 StackFrame::Type type() const {
1453 return StackFrameTypeBits::decode(minor_key_);
1454 }
1455
1456 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1457
1458 int handler_offset_;
1459
1460 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1461 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001462};
1463
1464
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465class ArgumentsAccessStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001466 public:
1467 enum Type {
1468 READ_ELEMENT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 NEW_SLOPPY_FAST,
1470 NEW_SLOPPY_SLOW,
Steve Block44f0eee2011-05-26 01:26:41 +01001471 NEW_STRICT
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001472 };
1473
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474 ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1475 minor_key_ = TypeBits::encode(type);
1476 }
1477
1478 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
1479 if (type() == READ_ELEMENT) {
1480 return ArgumentsAccessReadDescriptor(isolate());
1481 }
1482 return ContextOnlyDescriptor(isolate());
1483 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001484
1485 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001486 Type type() const { return TypeBits::decode(minor_key_); }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001487
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001488 void GenerateReadElement(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001489 void GenerateNewStrict(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001490 void GenerateNewSloppyFast(MacroAssembler* masm);
1491 void GenerateNewSloppySlow(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001492
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001493 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
1494
1495 class TypeBits : public BitField<Type, 0, 2> {};
1496
1497 DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001498};
1499
1500
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501class RegExpExecStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001502 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001504
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001505 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1506 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001507};
1508
1509
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510class RegExpConstructResultStub FINAL : public HydrogenCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001511 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001512 explicit RegExpConstructResultStub(Isolate* isolate)
1513 : HydrogenCodeStub(isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001514
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001515 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1516 static const int kLength = 0;
1517 static const int kIndex = 1;
1518 static const int kInput = 2;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001519
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1521 DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001522};
1523
1524
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525class CallFunctionStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001526 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527 CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1528 : PlatformCodeStub(isolate) {
1529 DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1530 minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001531 }
1532
Ben Murdoch086aeea2011-05-13 15:57:08 +01001533 static int ExtractArgcFromMinorKey(int minor_key) {
1534 return ArgcBits::decode(minor_key);
1535 }
1536
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001537 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001538 int argc() const { return ArgcBits::decode(minor_key_); }
1539 int flags() const { return FlagBits::decode(minor_key_); }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001540
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 bool CallAsMethod() const {
1542 return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1543 }
1544
1545 bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1546
1547 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001548
1549 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550 class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1551 class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1552 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001553
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001554 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1555 DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001556};
1557
1558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001559class CallConstructStub: public PlatformCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001560 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1562 : PlatformCodeStub(isolate) {
1563 minor_key_ = FlagBits::encode(flags);
1564 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001565
1566 virtual void FinishCode(Handle<Code> code) {
1567 code->set_has_function_cache(RecordCallTarget());
1568 }
1569
1570 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001572
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001573 bool RecordCallTarget() const {
1574 return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001575 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001576
1577 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
1578
1579 class FlagBits : public BitField<CallConstructorFlags, 0, 1> {};
1580
1581 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1582 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001583};
1584
1585
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001586enum StringIndexFlags {
1587 // Accepts smis or heap numbers.
1588 STRING_INDEX_IS_NUMBER,
1589
1590 // Accepts smis or heap numbers that are valid array indices
1591 // (ECMA-262 15.4). Invalid indices are reported as being out of
1592 // range.
1593 STRING_INDEX_IS_ARRAY_INDEX
1594};
1595
1596
1597// Generates code implementing String.prototype.charCodeAt.
1598//
1599// Only supports the case when the receiver is a string and the index
1600// is a number (smi or heap number) that is a valid index into the
1601// string. Additional index constraints are specified by the
1602// flags. Otherwise, bails out to the provided labels.
1603//
1604// Register usage: |object| may be changed to another string in a way
1605// that doesn't affect charCodeAt/charAt semantics, |index| is
1606// preserved, |scratch| and |result| are clobbered.
1607class StringCharCodeAtGenerator {
1608 public:
1609 StringCharCodeAtGenerator(Register object,
1610 Register index,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001611 Register result,
1612 Label* receiver_not_string,
1613 Label* index_not_number,
1614 Label* index_out_of_range,
1615 StringIndexFlags index_flags)
1616 : object_(object),
1617 index_(index),
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001618 result_(result),
1619 receiver_not_string_(receiver_not_string),
1620 index_not_number_(index_not_number),
1621 index_out_of_range_(index_out_of_range),
1622 index_flags_(index_flags) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 DCHECK(!result_.is(object_));
1624 DCHECK(!result_.is(index_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001625 }
1626
1627 // Generates the fast case code. On the fallthrough path |result|
1628 // register contains the result.
1629 void GenerateFast(MacroAssembler* masm);
1630
1631 // Generates the slow case code. Must not be naturally
1632 // reachable. Expected to be put after a ret instruction (e.g., in
1633 // deferred code). Always jumps back to the fast case.
1634 void GenerateSlow(MacroAssembler* masm,
1635 const RuntimeCallHelper& call_helper);
1636
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637 // Skip handling slow case and directly jump to bailout.
1638 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1639 masm->bind(&index_not_smi_);
1640 masm->bind(&call_runtime_);
1641 masm->jmp(bailout);
1642 }
1643
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001644 private:
1645 Register object_;
1646 Register index_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001647 Register result_;
1648
1649 Label* receiver_not_string_;
1650 Label* index_not_number_;
1651 Label* index_out_of_range_;
1652
1653 StringIndexFlags index_flags_;
1654
1655 Label call_runtime_;
1656 Label index_not_smi_;
1657 Label got_smi_index_;
1658 Label exit_;
1659
1660 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1661};
1662
1663
1664// Generates code for creating a one-char string from a char code.
1665class StringCharFromCodeGenerator {
1666 public:
1667 StringCharFromCodeGenerator(Register code,
1668 Register result)
1669 : code_(code),
1670 result_(result) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671 DCHECK(!code_.is(result_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001672 }
1673
1674 // Generates the fast case code. On the fallthrough path |result|
1675 // register contains the result.
1676 void GenerateFast(MacroAssembler* masm);
1677
1678 // Generates the slow case code. Must not be naturally
1679 // reachable. Expected to be put after a ret instruction (e.g., in
1680 // deferred code). Always jumps back to the fast case.
1681 void GenerateSlow(MacroAssembler* masm,
1682 const RuntimeCallHelper& call_helper);
1683
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001684 // Skip handling slow case and directly jump to bailout.
1685 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1686 masm->bind(&slow_case_);
1687 masm->jmp(bailout);
1688 }
1689
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001690 private:
1691 Register code_;
1692 Register result_;
1693
1694 Label slow_case_;
1695 Label exit_;
1696
1697 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1698};
1699
1700
1701// Generates code implementing String.prototype.charAt.
1702//
1703// Only supports the case when the receiver is a string and the index
1704// is a number (smi or heap number) that is a valid index into the
1705// string. Additional index constraints are specified by the
1706// flags. Otherwise, bails out to the provided labels.
1707//
1708// Register usage: |object| may be changed to another string in a way
1709// that doesn't affect charCodeAt/charAt semantics, |index| is
1710// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1711class StringCharAtGenerator {
1712 public:
1713 StringCharAtGenerator(Register object,
1714 Register index,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001715 Register scratch,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001716 Register result,
1717 Label* receiver_not_string,
1718 Label* index_not_number,
1719 Label* index_out_of_range,
1720 StringIndexFlags index_flags)
1721 : char_code_at_generator_(object,
1722 index,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001723 scratch,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001724 receiver_not_string,
1725 index_not_number,
1726 index_out_of_range,
1727 index_flags),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001728 char_from_code_generator_(scratch, result) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001729
1730 // Generates the fast case code. On the fallthrough path |result|
1731 // register contains the result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001732 void GenerateFast(MacroAssembler* masm) {
1733 char_code_at_generator_.GenerateFast(masm);
1734 char_from_code_generator_.GenerateFast(masm);
1735 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001736
1737 // Generates the slow case code. Must not be naturally
1738 // reachable. Expected to be put after a ret instruction (e.g., in
1739 // deferred code). Always jumps back to the fast case.
1740 void GenerateSlow(MacroAssembler* masm,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001741 const RuntimeCallHelper& call_helper) {
1742 char_code_at_generator_.GenerateSlow(masm, call_helper);
1743 char_from_code_generator_.GenerateSlow(masm, call_helper);
1744 }
1745
1746 // Skip handling slow case and directly jump to bailout.
1747 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1748 char_code_at_generator_.SkipSlow(masm, bailout);
1749 char_from_code_generator_.SkipSlow(masm, bailout);
1750 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001751
1752 private:
1753 StringCharCodeAtGenerator char_code_at_generator_;
1754 StringCharFromCodeGenerator char_from_code_generator_;
1755
1756 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1757};
1758
Ben Murdoch086aeea2011-05-13 15:57:08 +01001759
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001760class LoadDictionaryElementStub : public HydrogenCodeStub {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001761 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001762 explicit LoadDictionaryElementStub(Isolate* isolate)
1763 : HydrogenCodeStub(isolate) {}
Ben Murdoch086aeea2011-05-13 15:57:08 +01001764
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001765 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1766 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001767};
1768
Ben Murdoch257744e2011-11-30 15:57:28 +00001769
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770class KeyedLoadGenericStub : public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00001771 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001772 explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdoch257744e2011-11-30 15:57:28 +00001773
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001774 virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
1775 virtual InlineCacheState GetICState() const { return GENERIC; }
Ben Murdoch257744e2011-11-30 15:57:28 +00001776
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1778 DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00001779};
1780
1781
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001782class LoadICTrampolineStub : public PlatformCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00001783 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001784 LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
1785 : PlatformCodeStub(isolate) {
1786 minor_key_ = state.GetExtraICState();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001787 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001788
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001789 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1790
1791 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1792 return GENERIC;
1793 }
1794
1795 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1796 return static_cast<ExtraICState>(minor_key_);
1797 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001798
Ben Murdoch257744e2011-11-30 15:57:28 +00001799 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001800 LoadICState state() const {
1801 return LoadICState(static_cast<ExtraICState>(minor_key_));
1802 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001803
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadICTrampoline);
1805 DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00001806};
1807
1808
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001809class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
1810 public:
1811 explicit KeyedLoadICTrampolineStub(Isolate* isolate)
1812 : LoadICTrampolineStub(isolate, LoadICState(0)) {}
1813
1814 virtual Code::Kind GetCodeKind() const OVERRIDE {
1815 return Code::KEYED_LOAD_IC;
1816 }
1817
1818 DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
1819};
1820
1821
1822class MegamorphicLoadStub : public HydrogenCodeStub {
1823 public:
1824 MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
1825 : HydrogenCodeStub(isolate) {
1826 set_sub_minor_key(state.GetExtraICState());
1827 }
1828
1829 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1830
1831 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1832 return MEGAMORPHIC;
1833 }
1834
1835 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1836 return static_cast<ExtraICState>(sub_minor_key());
1837 }
1838
1839 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1840 DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
1841};
1842
1843
1844class VectorLoadStub : public HydrogenCodeStub {
1845 public:
1846 explicit VectorLoadStub(Isolate* isolate, const LoadICState& state)
1847 : HydrogenCodeStub(isolate) {
1848 set_sub_minor_key(state.GetExtraICState());
1849 }
1850
1851 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1852
1853 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1854 return GENERIC;
1855 }
1856
1857 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1858 return static_cast<ExtraICState>(sub_minor_key());
1859 }
1860
1861 private:
1862 LoadICState state() const { return LoadICState(GetExtraICState()); }
1863
1864 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1865 DEFINE_HYDROGEN_CODE_STUB(VectorLoad, HydrogenCodeStub);
1866};
1867
1868
1869class VectorKeyedLoadStub : public VectorLoadStub {
1870 public:
1871 explicit VectorKeyedLoadStub(Isolate* isolate)
1872 : VectorLoadStub(isolate, LoadICState(0)) {}
1873
1874 virtual Code::Kind GetCodeKind() const OVERRIDE {
1875 return Code::KEYED_LOAD_IC;
1876 }
1877
1878 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1879 DEFINE_HYDROGEN_CODE_STUB(VectorKeyedLoad, VectorLoadStub);
1880};
1881
1882
1883class DoubleToIStub : public PlatformCodeStub {
1884 public:
1885 DoubleToIStub(Isolate* isolate, Register source, Register destination,
1886 int offset, bool is_truncating, bool skip_fastpath = false)
1887 : PlatformCodeStub(isolate) {
1888 minor_key_ = SourceRegisterBits::encode(source.code()) |
1889 DestinationRegisterBits::encode(destination.code()) |
1890 OffsetBits::encode(offset) |
1891 IsTruncatingBits::encode(is_truncating) |
1892 SkipFastPathBits::encode(skip_fastpath) |
1893 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1894 }
1895
1896 virtual bool SometimesSetsUpAFrame() { return false; }
1897
1898 private:
1899 Register source() const {
1900 return Register::from_code(SourceRegisterBits::decode(minor_key_));
1901 }
1902 Register destination() const {
1903 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
1904 }
1905 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
1906 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
1907 int offset() const { return OffsetBits::decode(minor_key_); }
1908
1909 static const int kBitsPerRegisterNumber = 6;
1910 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1911 class SourceRegisterBits:
1912 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1913 class DestinationRegisterBits:
1914 public BitField<int, kBitsPerRegisterNumber,
1915 kBitsPerRegisterNumber> {}; // NOLINT
1916 class IsTruncatingBits:
1917 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1918 class OffsetBits:
1919 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1920 class SkipFastPathBits:
1921 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1922 class SSE3Bits:
1923 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
1924
1925 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1926 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
1927};
1928
1929
1930class LoadFastElementStub : public HydrogenCodeStub {
1931 public:
1932 LoadFastElementStub(Isolate* isolate, bool is_js_array,
1933 ElementsKind elements_kind)
1934 : HydrogenCodeStub(isolate) {
1935 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1936 IsJSArrayBits::encode(is_js_array));
1937 }
1938
1939 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1940
1941 ElementsKind elements_kind() const {
1942 return ElementsKindBits::decode(sub_minor_key());
1943 }
1944
1945 private:
1946 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1947 class IsJSArrayBits: public BitField<bool, 8, 1> {};
1948
1949 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1950 DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
1951};
1952
1953
1954class StoreFastElementStub : public HydrogenCodeStub {
1955 public:
1956 StoreFastElementStub(Isolate* isolate, bool is_js_array,
1957 ElementsKind elements_kind, KeyedAccessStoreMode mode)
1958 : HydrogenCodeStub(isolate) {
1959 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1960 IsJSArrayBits::encode(is_js_array) |
1961 StoreModeBits::encode(mode));
1962 }
1963
1964 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1965
1966 ElementsKind elements_kind() const {
1967 return ElementsKindBits::decode(sub_minor_key());
1968 }
1969
1970 KeyedAccessStoreMode store_mode() const {
1971 return StoreModeBits::decode(sub_minor_key());
1972 }
1973
1974 private:
1975 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1976 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1977 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1978
1979 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
1980 DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
1981};
1982
1983
1984class TransitionElementsKindStub : public HydrogenCodeStub {
1985 public:
1986 TransitionElementsKindStub(Isolate* isolate,
1987 ElementsKind from_kind,
1988 ElementsKind to_kind,
1989 bool is_js_array) : HydrogenCodeStub(isolate) {
1990 set_sub_minor_key(FromKindBits::encode(from_kind) |
1991 ToKindBits::encode(to_kind) |
1992 IsJSArrayBits::encode(is_js_array));
1993 }
1994
1995 ElementsKind from_kind() const {
1996 return FromKindBits::decode(sub_minor_key());
1997 }
1998
1999 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2000
2001 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2002
2003 private:
2004 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2005 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2006 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2007
2008 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2009 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2010};
2011
2012
2013class ArrayConstructorStubBase : public HydrogenCodeStub {
2014 public:
2015 ArrayConstructorStubBase(Isolate* isolate,
2016 ElementsKind kind,
2017 AllocationSiteOverrideMode override_mode)
2018 : HydrogenCodeStub(isolate) {
2019 // It only makes sense to override local allocation site behavior
2020 // if there is a difference between the global allocation site policy
2021 // for an ElementsKind and the desired usage of the stub.
2022 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2023 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2024 set_sub_minor_key(ElementsKindBits::encode(kind) |
2025 AllocationSiteOverrideModeBits::encode(override_mode));
2026 }
2027
2028 ElementsKind elements_kind() const {
2029 return ElementsKindBits::decode(sub_minor_key());
2030 }
2031
2032 AllocationSiteOverrideMode override_mode() const {
2033 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2034 }
2035
2036 static void GenerateStubsAheadOfTime(Isolate* isolate);
2037
2038 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2039 static const int kConstructor = 0;
2040 static const int kAllocationSite = 1;
2041
2042 protected:
2043 OStream& BasePrintName(OStream& os, const char* name) const; // NOLINT
2044
2045 private:
2046 // Ensure data fits within available bits.
2047 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2048
2049 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2050 class AllocationSiteOverrideModeBits: public
2051 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2052
2053 DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2054};
2055
2056
2057class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2058 public:
2059 ArrayNoArgumentConstructorStub(
2060 Isolate* isolate,
2061 ElementsKind kind,
2062 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2063 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2064 }
2065
2066 private:
2067 virtual void PrintName(OStream& os) const OVERRIDE { // NOLINT
2068 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2069 }
2070
2071 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2072 DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2073 ArrayConstructorStubBase);
2074};
2075
2076
2077class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2078 public:
2079 ArraySingleArgumentConstructorStub(
2080 Isolate* isolate,
2081 ElementsKind kind,
2082 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2083 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2084 }
2085
2086 private:
2087 virtual void PrintName(OStream& os) const { // NOLINT
2088 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2089 }
2090
2091 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2092 DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2093 ArrayConstructorStubBase);
2094};
2095
2096
2097class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2098 public:
2099 ArrayNArgumentsConstructorStub(
2100 Isolate* isolate,
2101 ElementsKind kind,
2102 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2103 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2104 }
2105
2106 private:
2107 virtual void PrintName(OStream& os) const { // NOLINT
2108 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2109 }
2110
2111 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2112 DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2113 ArrayConstructorStubBase);
2114};
2115
2116
2117class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2118 public:
2119 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2120 : HydrogenCodeStub(isolate) {
2121 set_sub_minor_key(ElementsKindBits::encode(kind));
2122 }
2123
2124 static void GenerateStubsAheadOfTime(Isolate* isolate);
2125
2126 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2127 static const int kConstructor = 0;
2128
2129 ElementsKind elements_kind() const {
2130 return ElementsKindBits::decode(sub_minor_key());
2131 }
2132
2133 private:
2134 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2135
2136 DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2137};
2138
2139
2140class InternalArrayNoArgumentConstructorStub : public
2141 InternalArrayConstructorStubBase {
2142 public:
2143 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2144 ElementsKind kind)
2145 : InternalArrayConstructorStubBase(isolate, kind) { }
2146
2147 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2148 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2149 InternalArrayConstructorStubBase);
2150};
2151
2152
2153class InternalArraySingleArgumentConstructorStub : public
2154 InternalArrayConstructorStubBase {
2155 public:
2156 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2157 ElementsKind kind)
2158 : InternalArrayConstructorStubBase(isolate, kind) { }
2159
2160 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2161 DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2162 InternalArrayConstructorStubBase);
2163};
2164
2165
2166class InternalArrayNArgumentsConstructorStub : public
2167 InternalArrayConstructorStubBase {
2168 public:
2169 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2170 : InternalArrayConstructorStubBase(isolate, kind) { }
2171
2172 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2173 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2174 InternalArrayConstructorStubBase);
2175};
2176
2177
2178class StoreElementStub : public PlatformCodeStub {
2179 public:
2180 StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2181 : PlatformCodeStub(isolate) {
2182 minor_key_ = ElementsKindBits::encode(elements_kind);
2183 }
2184
2185 private:
2186 ElementsKind elements_kind() const {
2187 return ElementsKindBits::decode(minor_key_);
2188 }
2189
2190 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2191
2192 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2193 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2194};
2195
2196
2197class ToBooleanStub: public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002198 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002199 enum Type {
2200 UNDEFINED,
2201 BOOLEAN,
2202 NULL_TYPE,
2203 SMI,
2204 SPEC_OBJECT,
2205 STRING,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002206 SYMBOL,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002207 HEAP_NUMBER,
2208 NUMBER_OF_TYPES
2209 };
2210
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002211 enum ResultMode {
2212 RESULT_AS_SMI, // For Smi(1) on truthy value, Smi(0) otherwise.
2213 RESULT_AS_ODDBALL, // For {true} on truthy value, {false} otherwise.
2214 RESULT_AS_INVERSE_ODDBALL // For {false} on truthy value, {true} otherwise.
2215 };
2216
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002217 // At most 8 different types can be distinguished, because the Code object
2218 // only has room for a single byte to hold a set of these types. :-P
2219 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2220
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002221 class Types : public EnumSet<Type, byte> {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002222 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002223 Types() : EnumSet<Type, byte>(0) {}
2224 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002225
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002226 byte ToByte() const { return ToIntegral(); }
2227 bool UpdateStatus(Handle<Object> object);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002228 bool NeedsMap() const;
2229 bool CanBeUndetectable() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002230 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002231
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002232 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002233 };
2234
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002235 ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2236 : HydrogenCodeStub(isolate) {
2237 set_sub_minor_key(TypesBits::encode(types.ToByte()) |
2238 ResultModeBits::encode(mode));
2239 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002240
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002241 ToBooleanStub(Isolate* isolate, ExtraICState state)
2242 : HydrogenCodeStub(isolate) {
2243 set_sub_minor_key(TypesBits::encode(static_cast<byte>(state)) |
2244 ResultModeBits::encode(RESULT_AS_SMI));
2245 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002246
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002247 bool UpdateStatus(Handle<Object> object);
2248 Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2249 ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2250
2251 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2252 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
Ben Murdoch257744e2011-11-30 15:57:28 +00002253
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002254 virtual bool SometimesSetsUpAFrame() { return false; }
2255
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002256 static Handle<Code> GetUninitialized(Isolate* isolate) {
2257 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002258 }
2259
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002260 virtual ExtraICState GetExtraICState() const { return types().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002261
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002262 virtual InlineCacheState GetICState() const {
2263 if (types().IsEmpty()) {
2264 return ::v8::internal::UNINITIALIZED;
2265 } else {
2266 return MONOMORPHIC;
2267 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002268 }
2269
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002270 private:
2271 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2272 : HydrogenCodeStub(isolate, init_state) {
2273 set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2274 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002275
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002276 class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2277 class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002278
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002279 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2280 DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002281};
2282
2283
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002284OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2285
2286
2287class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002288 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002289 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2290 ElementsKind to_kind, bool is_jsarray,
2291 KeyedAccessStoreMode store_mode)
2292 : HydrogenCodeStub(isolate) {
2293 set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2294 IsJSArrayBits::encode(is_jsarray) |
2295 StoreModeBits::encode(store_mode));
2296 }
2297
2298 ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2299 ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2300 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2301 KeyedAccessStoreMode store_mode() const {
2302 return StoreModeBits::decode(sub_minor_key());
2303 }
2304
2305 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2306 enum ParameterIndices {
2307 kValueIndex,
2308 kMapIndex,
2309 kKeyIndex,
2310 kObjectIndex,
2311 kParameterCount
2312 };
2313
2314 static const Register ValueRegister() {
2315 return ElementTransitionAndStoreDescriptor::ValueRegister();
2316 }
2317 static const Register MapRegister() {
2318 return ElementTransitionAndStoreDescriptor::MapRegister();
2319 }
2320 static const Register KeyRegister() {
2321 return ElementTransitionAndStoreDescriptor::NameRegister();
2322 }
2323 static const Register ObjectRegister() {
2324 return ElementTransitionAndStoreDescriptor::ReceiverRegister();
2325 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002326
2327 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002328 class FromBits : public BitField<ElementsKind, 0, 8> {};
2329 class ToBits : public BitField<ElementsKind, 8, 8> {};
2330 class IsJSArrayBits : public BitField<bool, 16, 1> {};
2331 class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002332
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002333 DEFINE_CALL_INTERFACE_DESCRIPTOR(ElementTransitionAndStore);
2334 DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002335};
2336
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002337
2338class StoreArrayLiteralElementStub : public PlatformCodeStub {
2339 public:
2340 explicit StoreArrayLiteralElementStub(Isolate* isolate)
2341 : PlatformCodeStub(isolate) { }
2342
2343 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2344 DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2345};
2346
2347
2348class StubFailureTrampolineStub : public PlatformCodeStub {
2349 public:
2350 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2351 : PlatformCodeStub(isolate) {
2352 minor_key_ = FunctionModeField::encode(function_mode);
2353 }
2354
2355 static void GenerateAheadOfTime(Isolate* isolate);
2356
2357 private:
2358 StubFunctionMode function_mode() const {
2359 return FunctionModeField::decode(minor_key_);
2360 }
2361
2362 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2363
2364 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2365 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2366};
2367
2368
2369class ProfileEntryHookStub : public PlatformCodeStub {
2370 public:
2371 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2372
2373 // The profile entry hook function is not allowed to cause a GC.
2374 virtual bool SometimesSetsUpAFrame() { return false; }
2375
2376 // Generates a call to the entry hook if it's enabled.
2377 static void MaybeCallEntryHook(MacroAssembler* masm);
2378
2379 private:
2380 static void EntryHookTrampoline(intptr_t function,
2381 intptr_t stack_pointer,
2382 Isolate* isolate);
2383
2384 // ProfileEntryHookStub is called at the start of a function, so it has the
2385 // same register set.
2386 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2387 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2388};
2389
2390
2391class StoreBufferOverflowStub : public PlatformCodeStub {
2392 public:
2393 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2394 : PlatformCodeStub(isolate) {
2395 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2396 }
2397
2398 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
2399 virtual bool SometimesSetsUpAFrame() { return false; }
2400
2401 private:
2402 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2403
2404 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2405
2406 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2407 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2408};
2409
2410
2411class SubStringStub : public PlatformCodeStub {
2412 public:
2413 explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2414
2415 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2416 DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2417};
2418
2419
2420class StringCompareStub : public PlatformCodeStub {
2421 public:
2422 explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2423
2424 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2425 DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2426};
2427
2428
2429#undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2430#undef DEFINE_PLATFORM_CODE_STUB
2431#undef DEFINE_HANDLER_CODE_STUB
2432#undef DEFINE_HYDROGEN_CODE_STUB
2433#undef DEFINE_CODE_STUB
2434#undef DEFINE_CODE_STUB_BASE
Steve Blocka7e24c12009-10-30 11:49:00 +00002435} } // namespace v8::internal
2436
2437#endif // V8_CODE_STUBS_H_