blob: 8448e557f240ac496e4e0962e8489dfdec3ab012 [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) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042 V(LoadIndexedString) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 V(MathPow) \
44 V(ProfileEntryHook) \
45 V(RecordWrite) \
46 V(RegExpExec) \
47 V(StoreArrayLiteralElement) \
48 V(StoreBufferOverflow) \
49 V(StoreElement) \
50 V(StringCompare) \
51 V(StubFailureTrampoline) \
52 V(SubString) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053 V(ToNumber) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054 /* HydrogenCodeStubs */ \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 V(AllocateHeapNumber) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 V(ArrayNArgumentsConstructor) \
57 V(ArrayNoArgumentConstructor) \
58 V(ArraySingleArgumentConstructor) \
59 V(BinaryOpIC) \
60 V(BinaryOpWithAllocationSite) \
61 V(CompareNilIC) \
62 V(CreateAllocationSite) \
63 V(ElementsTransitionAndStore) \
64 V(FastCloneShallowArray) \
65 V(FastCloneShallowObject) \
66 V(FastNewClosure) \
67 V(FastNewContext) \
68 V(InternalArrayNArgumentsConstructor) \
69 V(InternalArrayNoArgumentConstructor) \
70 V(InternalArraySingleArgumentConstructor) \
71 V(KeyedLoadGeneric) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 V(LoadScriptContextField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 V(LoadDictionaryElement) \
74 V(LoadFastElement) \
75 V(MegamorphicLoad) \
76 V(NameDictionaryLookup) \
77 V(NumberToString) \
78 V(RegExpConstructResult) \
79 V(StoreFastElement) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 V(StoreScriptContextField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 V(StringAdd) \
82 V(ToBoolean) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 V(TransitionElementsKind) \
84 V(VectorKeyedLoad) \
85 V(VectorLoad) \
86 /* IC Handler stubs */ \
87 V(LoadConstant) \
88 V(LoadField) \
89 V(KeyedLoadSloppyArguments) \
90 V(StoreField) \
91 V(StoreGlobal) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092 V(StoreTransition) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 V(StringLength)
Steve Blockd0582a62009-12-15 09:54:21 +000094
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095// List of code stubs only used on ARM 32 bits platforms.
96#if V8_TARGET_ARCH_ARM
Emily Bernierd0a1eb72015-03-24 16:35:39 -040097#define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098
Steve Blockd0582a62009-12-15 09:54:21 +000099#else
100#define CODE_STUB_LIST_ARM(V)
101#endif
102
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103// List of code stubs only used on ARM 64 bits platforms.
104#if V8_TARGET_ARCH_ARM64
105#define CODE_STUB_LIST_ARM64(V) \
106 V(DirectCEntry) \
107 V(RestoreRegistersState) \
108 V(StoreRegistersState)
109
110#else
111#define CODE_STUB_LIST_ARM64(V)
112#endif
113
Steve Block44f0eee2011-05-26 01:26:41 +0100114// List of code stubs only used on MIPS platforms.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115#if V8_TARGET_ARCH_MIPS
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400116#define CODE_STUB_LIST_MIPS(V) \
117 V(DirectCEntry) \
118 V(RestoreRegistersState) \
119 V(StoreRegistersState)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120#elif V8_TARGET_ARCH_MIPS64
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121#define CODE_STUB_LIST_MIPS(V) \
122 V(DirectCEntry) \
123 V(RestoreRegistersState) \
124 V(StoreRegistersState)
Steve Block44f0eee2011-05-26 01:26:41 +0100125#else
126#define CODE_STUB_LIST_MIPS(V)
127#endif
128
Steve Blockd0582a62009-12-15 09:54:21 +0000129// Combined list of code stubs.
130#define CODE_STUB_LIST(V) \
131 CODE_STUB_LIST_ALL_PLATFORMS(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100132 CODE_STUB_LIST_ARM(V) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 CODE_STUB_LIST_ARM64(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100134 CODE_STUB_LIST_MIPS(V)
Steve Blocka7e24c12009-10-30 11:49:00 +0000135
136// Stub is base classes of all stubs.
137class CodeStub BASE_EMBEDDED {
138 public:
139 enum Major {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400140 // TODO(mvstanton): eliminate the NoCache key by getting rid
141 // of the non-monomorphic-cache.
142 NoCache = 0, // marker for stubs that do custom caching]
Steve Blockd0582a62009-12-15 09:54:21 +0000143#define DEF_ENUM(name) name,
144 CODE_STUB_LIST(DEF_ENUM)
145#undef DEF_ENUM
Steve Blocka7e24c12009-10-30 11:49:00 +0000146 NUMBER_OF_IDS
147 };
148
149 // Retrieve the code for the stub. Generate the code if needed.
150 Handle<Code> GetCode();
151
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 // Retrieve the code for the stub, make and return a copy of the code.
153 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
154
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 static Major MajorKeyFromKey(uint32_t key) {
156 return static_cast<Major>(MajorKeyBits::decode(key));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100157 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 static uint32_t MinorKeyFromKey(uint32_t key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 return MinorKeyBits::decode(key);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100160 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100161
162 // Gets the major key from a code object that is a code stub or binary op IC.
163 static Major GetMajorKey(Code* code_stub) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 return MajorKeyFromKey(code_stub->stub_key());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100165 }
166
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
168
Andrei Popescu31002712010-02-23 13:46:05 +0000169 static const char* MajorName(Major major_key, bool allow_unknown_keys);
Steve Blocka7e24c12009-10-30 11:49:00 +0000170
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000172 virtual ~CodeStub() {}
173
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 static void GenerateStubsAheadOfTime(Isolate* isolate);
175 static void GenerateFPStubs(Isolate* isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100176
177 // Some stubs put untagged junk on the stack that cannot be scanned by the
178 // GC. This means that we must be statically sure that no GC can occur while
179 // they are running. If that is the case they should override this to return
180 // true, which will cause an assertion if we try to call something that can
181 // GC or if we try to put a stack frame on top of the junk, which would not
182 // result in a traversable stack.
183 virtual bool SometimesSetsUpAFrame() { return true; }
184
185 // Lookup the code in the (possibly custom) cache.
186 bool FindCodeInCache(Code** code_out);
187
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
191
192 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
193 CodeStubDescriptor* desc);
194
195 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
196
197 // Returns information for computing the number key.
198 virtual Major MajorKey() const = 0;
199 uint32_t MinorKey() const { return minor_key_; }
200
201 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
202 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
203 virtual Code::StubType GetStubType() {
204 return Code::NORMAL;
205 }
206
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 s.PrintName(os);
209 return os;
210 }
211
212 Isolate* isolate() const { return isolate_; }
213
214 protected:
215 CodeStub(uint32_t key, Isolate* isolate)
216 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
Leon Clarkee46be812010-01-19 14:06:41 +0000217
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 // Generates the assembler code for the stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 virtual Handle<Code> GenerateCode() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 // Returns whether the code generated for this stub needs to be allocated as
222 // a fixed (non-moveable) code object.
223 virtual bool NeedsImmovableCode() { return false; }
224
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225 virtual void PrintName(std::ostream& os) const; // NOLINT
226 virtual void PrintBaseName(std::ostream& os) const; // NOLINT
227 virtual void PrintState(std::ostream& os) const { ; } // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228
229 // Computes the key based on major and minor.
230 uint32_t GetKey() {
231 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
232 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
233 }
234
235 uint32_t minor_key_;
236
237 private:
Leon Clarkee46be812010-01-19 14:06:41 +0000238 // Perform bookkeeping required after code generation when stub code is
239 // initially generated.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 void RecordCodeGeneration(Handle<Code> code);
Leon Clarkee46be812010-01-19 14:06:41 +0000241
Ben Murdochb0fe1622011-05-05 13:52:32 +0100242 // Finish the code object after it has been generated.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100243 virtual void FinishCode(Handle<Code> code) { }
244
245 // Activate newly generated stub. Is called after
246 // registering stub in the stub cache.
247 virtual void Activate(Code* code) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100248
Ben Murdoch257744e2011-11-30 15:57:28 +0000249 // BinaryOpStub needs to override this.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250 virtual Code::Kind GetCodeKind() const;
Steve Block6ded16b2010-05-10 14:33:55 +0100251
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100252 // Add the code to a specialized cache, specific to an individual
253 // stub type. Please note, this method must add the code object to a
254 // roots object, otherwise we will remove the code during GC.
255 virtual void AddToSpecialCache(Handle<Code> new_object) { }
256
257 // Find code in a specialized cache, work is delegated to the specific stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 virtual bool FindCodeInSpecialCache(Code** code_out) {
259 return false;
260 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100261
262 // If a stub uses a special cache override this.
263 virtual bool UseSpecialCache() { return false; }
264
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 // We use this dispatch to statically instantiate the correct code stub for
266 // the given stub key and call the passed function with that code stub.
267 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
268 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
269 DispatchedCall call);
Steve Blocka7e24c12009-10-30 11:49:00 +0000270
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
Steve Block44f0eee2011-05-26 01:26:41 +0100272
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
274 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
275 class MinorKeyBits: public BitField<uint32_t,
276 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000277
278 friend class BreakPointIterator;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279
280 Isolate* isolate_;
281};
282
283
284#define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
285 public: \
286 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
287 \
288 private: \
289 DISALLOW_COPY_AND_ASSIGN(NAME)
290
291
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400292#define DEFINE_CODE_STUB(NAME, SUPER) \
293 protected: \
294 inline Major MajorKey() const OVERRIDE { return NAME; }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
296
297
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400298#define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
299 private: \
300 void Generate(MacroAssembler* masm) OVERRIDE; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 DEFINE_CODE_STUB(NAME, SUPER)
302
303
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304#define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
305 public: \
306 void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE; \
307 Handle<Code> GenerateCode() OVERRIDE; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 DEFINE_CODE_STUB(NAME, SUPER)
309
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400310#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
311 public: \
312 Handle<Code> GenerateCode() OVERRIDE; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000313 DEFINE_CODE_STUB(NAME, SUPER)
314
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400315#define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
316 public: \
317 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
318 return NAME##Descriptor(isolate()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 }
320
321// There are some code stubs we just can't describe right now with a
322// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
323// An attempt to retrieve a descriptor will fail.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400324#define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
325 public: \
326 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
327 UNREACHABLE(); \
328 return CallInterfaceDescriptor(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 }
330
331
332class PlatformCodeStub : public CodeStub {
333 public:
334 // Retrieve the code for the stub. Generate the code if needed.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335 Handle<Code> GenerateCode() OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 Code::Kind GetCodeKind() const OVERRIDE { return Code::STUB; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338
339 protected:
340 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
341
342 // Generates the assembler code for the stub.
343 virtual void Generate(MacroAssembler* masm) = 0;
344
345 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
346};
347
348
349enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
350enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
351
352
353class CodeStubDescriptor {
354 public:
355 explicit CodeStubDescriptor(CodeStub* stub);
356
357 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
358
359 void Initialize(Address deoptimization_handler = NULL,
360 int hint_stack_parameter_count = -1,
361 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
362 void Initialize(Register stack_parameter_count,
363 Address deoptimization_handler = NULL,
364 int hint_stack_parameter_count = -1,
365 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
366 HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
367
368 void SetMissHandler(ExternalReference handler) {
369 miss_handler_ = handler;
370 has_miss_handler_ = true;
371 // Our miss handler infrastructure doesn't currently support
372 // variable stack parameter counts.
373 DCHECK(!stack_parameter_count_.is_valid());
374 }
375
376 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
377 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
378
379 int GetEnvironmentParameterCount() const {
380 return call_descriptor().GetEnvironmentParameterCount();
381 }
382
383 Representation GetEnvironmentParameterRepresentation(int index) const {
384 return call_descriptor().GetEnvironmentParameterRepresentation(index);
385 }
386
387 ExternalReference miss_handler() const {
388 DCHECK(has_miss_handler_);
389 return miss_handler_;
390 }
391
392 bool has_miss_handler() const {
393 return has_miss_handler_;
394 }
395
396 bool IsEnvironmentParameterCountRegister(int index) const {
397 return call_descriptor().GetEnvironmentParameterRegister(index).is(
398 stack_parameter_count_);
399 }
400
401 int GetHandlerParameterCount() const {
402 int params = call_descriptor().GetEnvironmentParameterCount();
403 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
404 params += 1;
405 }
406 return params;
407 }
408
409 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
410 Register stack_parameter_count() const { return stack_parameter_count_; }
411 StubFunctionMode function_mode() const { return function_mode_; }
412 Address deoptimization_handler() const { return deoptimization_handler_; }
413
414 private:
415 CallInterfaceDescriptor call_descriptor_;
416 Register stack_parameter_count_;
417 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
418 // return sequence. Default value is -1, which means it is ignored.
419 int hint_stack_parameter_count_;
420 StubFunctionMode function_mode_;
421
422 Address deoptimization_handler_;
423 HandlerArgumentsMode handler_arguments_mode_;
424
425 ExternalReference miss_handler_;
426 bool has_miss_handler_;
427};
428
429
430class HydrogenCodeStub : public CodeStub {
431 public:
432 enum InitializationState {
433 UNINITIALIZED,
434 INITIALIZED
435 };
436
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400437 Code::Kind GetCodeKind() const OVERRIDE { return Code::STUB; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438
439 template<class SubClass>
440 static Handle<Code> GetUninitialized(Isolate* isolate) {
441 SubClass::GenerateAheadOfTime(isolate);
442 return SubClass().GetCode(isolate);
443 }
444
445 // Retrieve the code for the stub. Generate the code if needed.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400446 Handle<Code> GenerateCode() OVERRIDE = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000447
448 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
449
450 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
451
452 template<class StateType>
453 void TraceTransition(StateType from, StateType to);
454
455 protected:
456 explicit HydrogenCodeStub(Isolate* isolate,
457 InitializationState state = INITIALIZED)
458 : CodeStub(isolate) {
459 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
460 }
461
462 void set_sub_minor_key(uint32_t key) {
463 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
464 }
465
466 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
467
468 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
469
470 private:
471 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
472 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
473
474 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
475
476 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000477};
478
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100479
480// Helper interface to prepare to/restore after making runtime calls.
481class RuntimeCallHelper {
482 public:
483 virtual ~RuntimeCallHelper() {}
484
485 virtual void BeforeCall(MacroAssembler* masm) const = 0;
486
487 virtual void AfterCall(MacroAssembler* masm) const = 0;
488
489 protected:
490 RuntimeCallHelper() {}
491
492 private:
493 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
494};
495
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100497} } // namespace v8::internal
498
499#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500#include "src/ia32/code-stubs-ia32.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100501#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502#include "src/x64/code-stubs-x64.h"
503#elif V8_TARGET_ARCH_ARM64
504#include "src/arm64/code-stubs-arm64.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100505#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506#include "src/arm/code-stubs-arm.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100507#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508#include "src/mips/code-stubs-mips.h"
509#elif V8_TARGET_ARCH_MIPS64
510#include "src/mips64/code-stubs-mips64.h"
511#elif V8_TARGET_ARCH_X87
512#include "src/x87/code-stubs-x87.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100513#else
514#error Unsupported target architecture.
515#endif
516
517namespace v8 {
518namespace internal {
519
520
Ben Murdochb0fe1622011-05-05 13:52:32 +0100521// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100522// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100523class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100524 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100525 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100526
527 virtual void BeforeCall(MacroAssembler* masm) const;
528
529 virtual void AfterCall(MacroAssembler* masm) const;
530};
531
532
533// Trivial RuntimeCallHelper implementation.
534class NopRuntimeCallHelper : public RuntimeCallHelper {
535 public:
536 NopRuntimeCallHelper() {}
537
538 virtual void BeforeCall(MacroAssembler* masm) const {}
539
540 virtual void AfterCall(MacroAssembler* masm) const {}
541};
542
543
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000544class NumberToStringStub FINAL : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100545 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100547
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
549 static const int kNumber = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100550
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
552 DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100553};
554
555
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556class FastNewClosureStub : public HydrogenCodeStub {
Steve Block1e0659c2011-05-24 12:43:12 +0100557 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
559 FunctionKind kind)
560 : HydrogenCodeStub(isolate) {
561 DCHECK(IsValidFunctionKind(kind));
562 set_sub_minor_key(StrictModeBits::encode(strict_mode) |
563 FunctionKindBits::encode(kind));
564 }
Steve Block1e0659c2011-05-24 12:43:12 +0100565
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 StrictMode strict_mode() const {
567 return StrictModeBits::decode(sub_minor_key());
568 }
569
570 FunctionKind kind() const {
571 return FunctionKindBits::decode(sub_minor_key());
572 }
573 bool is_arrow() const { return IsArrowFunction(kind()); }
574 bool is_generator() const { return IsGeneratorFunction(kind()); }
575 bool is_concise_method() const { return IsConciseMethod(kind()); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400576 bool is_default_constructor() const { return IsDefaultConstructor(kind()); }
Steve Block1e0659c2011-05-24 12:43:12 +0100577
578 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 class StrictModeBits : public BitField<StrictMode, 0, 1> {};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400580 class FunctionKindBits : public BitField<FunctionKind, 1, 4> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581
582 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
583 DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
Steve Block1e0659c2011-05-24 12:43:12 +0100584};
585
586
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587class FastNewContextStub FINAL : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100588 public:
589 static const int kMaximumSlots = 64;
590
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
592 DCHECK(slots > 0 && slots <= kMaximumSlots);
593 set_sub_minor_key(SlotsBits::encode(slots));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100594 }
595
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596 int slots() const { return SlotsBits::decode(sub_minor_key()); }
597
598 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
599 static const int kFunction = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100600
601 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000602 class SlotsBits : public BitField<int, 0, 8> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100603
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
605 DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100606};
607
608
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609class FastCloneShallowArrayStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100610 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 FastCloneShallowArrayStub(Isolate* isolate,
612 AllocationSiteMode allocation_site_mode)
613 : HydrogenCodeStub(isolate) {
614 set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100615 }
616
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 AllocationSiteMode allocation_site_mode() const {
618 return AllocationSiteModeBits::decode(sub_minor_key());
619 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100620
621 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100623
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
625 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100626};
627
628
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629class FastCloneShallowObjectStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100630 public:
631 // Maximum number of properties in copied object.
632 static const int kMaximumClonedProperties = 6;
633
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 FastCloneShallowObjectStub(Isolate* isolate, int length)
635 : HydrogenCodeStub(isolate) {
636 DCHECK_GE(length, 0);
637 DCHECK_LE(length, kMaximumClonedProperties);
638 set_sub_minor_key(LengthBits::encode(length));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100639 }
640
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 int length() const { return LengthBits::decode(sub_minor_key()); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100642
643 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644 class LengthBits : public BitField<int, 0, 4> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100645
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
647 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100648};
649
650
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651class CreateAllocationSiteStub : public HydrogenCodeStub {
652 public:
653 explicit CreateAllocationSiteStub(Isolate* isolate)
654 : HydrogenCodeStub(isolate) { }
655
656 static void GenerateAheadOfTime(Isolate* isolate);
657
658 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
659 DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
660};
661
662
663class InstanceofStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100664 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100665 enum Flags {
666 kNoFlags = 0,
Ben Murdoch086aeea2011-05-13 15:57:08 +0100667 kArgsInRegisters = 1 << 0,
668 kCallSiteInlineCheck = 1 << 1,
669 kReturnTrueFalseObject = 1 << 2
Ben Murdochb0fe1622011-05-05 13:52:32 +0100670 };
671
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672 InstanceofStub(Isolate* isolate, Flags flags) : PlatformCodeStub(isolate) {
673 minor_key_ = FlagBits::encode(flags);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 }
675
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676 static Register left() { return InstanceofDescriptor::left(); }
677 static Register right() { return InstanceofDescriptor::right(); }
678
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400679 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680 if (HasArgsInRegisters()) {
681 return InstanceofDescriptor(isolate());
682 }
683 return ContextOnlyDescriptor(isolate());
684 }
685
686 private:
687 Flags flags() const { return FlagBits::decode(minor_key_); }
688
689 bool HasArgsInRegisters() const { return (flags() & kArgsInRegisters) != 0; }
690
Ben Murdoch086aeea2011-05-13 15:57:08 +0100691 bool HasCallSiteInlineCheck() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692 return (flags() & kCallSiteInlineCheck) != 0;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100693 }
694
695 bool ReturnTrueFalseObject() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000696 return (flags() & kReturnTrueFalseObject) != 0;
Ben Murdoch086aeea2011-05-13 15:57:08 +0100697 }
698
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400699 void PrintName(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdoch086aeea2011-05-13 15:57:08 +0100700
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000701 class FlagBits : public BitField<Flags, 0, 3> {};
702
703 DEFINE_PLATFORM_CODE_STUB(Instanceof, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100704};
705
706
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707enum AllocationSiteOverrideMode {
708 DONT_OVERRIDE,
709 DISABLE_ALLOCATION_SITES,
710 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
711};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100712
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713
714class ArrayConstructorStub: public PlatformCodeStub {
715 public:
716 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
717
718 ArrayConstructorStub(Isolate* isolate, int argument_count);
719
720 explicit ArrayConstructorStub(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100721
722 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 ArgumentCountKey argument_count() const {
724 return ArgumentCountBits::decode(minor_key_);
725 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100726
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727 void GenerateDispatchToArrayStub(MacroAssembler* masm,
728 AllocationSiteOverrideMode mode);
729
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400730 void PrintName(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731
732 class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
733
734 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
735 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736};
737
738
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739class InternalArrayConstructorStub: public PlatformCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100740 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741 explicit InternalArrayConstructorStub(Isolate* isolate);
742
743 private:
744 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
745
746 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
747 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
748};
749
750
751class MathPowStub: public PlatformCodeStub {
752 public:
753 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
754
755 MathPowStub(Isolate* isolate, ExponentType exponent_type)
756 : PlatformCodeStub(isolate) {
757 minor_key_ = ExponentTypeBits::encode(exponent_type);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100758 }
759
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400760 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 if (exponent_type() == TAGGED) {
762 return MathPowTaggedDescriptor(isolate());
763 } else if (exponent_type() == INTEGER) {
764 return MathPowIntegerDescriptor(isolate());
765 }
766 // A CallInterfaceDescriptor doesn't specify double registers (yet).
767 return ContextOnlyDescriptor(isolate());
768 }
769
770 private:
771 ExponentType exponent_type() const {
772 return ExponentTypeBits::decode(minor_key_);
773 }
774
775 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
776
777 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
778};
779
780
781class CallICStub: public PlatformCodeStub {
782 public:
783 CallICStub(Isolate* isolate, const CallICState& state)
784 : PlatformCodeStub(isolate) {
785 minor_key_ = state.GetExtraICState();
786 }
787
788 static int ExtractArgcFromMinorKey(int minor_key) {
789 CallICState state(static_cast<ExtraICState>(minor_key));
790 return state.arg_count();
791 }
792
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400793 Code::Kind GetCodeKind() const OVERRIDE { return Code::CALL_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400795 InlineCacheState GetICState() const OVERRIDE { return DEFAULT; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000796
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400797 ExtraICState GetExtraICState() const FINAL {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 return static_cast<ExtraICState>(minor_key_);
799 }
800
801 protected:
802 bool CallAsMethod() const {
803 return state().call_type() == CallICState::METHOD;
804 }
805
806 int arg_count() const { return state().arg_count(); }
807
808 CallICState state() const {
809 return CallICState(static_cast<ExtraICState>(minor_key_));
810 }
811
812 // Code generation helpers.
813 void GenerateMiss(MacroAssembler* masm);
814
815 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400816 void PrintState(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817
818 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
819 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
820};
821
822
823class CallIC_ArrayStub: public CallICStub {
824 public:
825 CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
826 : CallICStub(isolate, state_in) {}
827
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400828 InlineCacheState GetICState() const FINAL { return MONOMORPHIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829
830 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400831 void PrintState(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832
833 DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
834};
835
836
837// TODO(verwaest): Translate to hydrogen code stub.
838class FunctionPrototypeStub : public PlatformCodeStub {
839 public:
840 explicit FunctionPrototypeStub(Isolate* isolate)
841 : PlatformCodeStub(isolate) {}
842
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400843 Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844
845 // TODO(mvstanton): only the receiver register is accessed. When this is
846 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
847 // should be created that just uses that register for more efficient code.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400848 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
849 if (FLAG_vector_ics) {
850 return VectorLoadICDescriptor(isolate());
851 }
852 return LoadDescriptor(isolate());
853 }
854
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
856};
857
858
859// TODO(mvstanton): Translate to hydrogen code stub.
860class LoadIndexedInterceptorStub : public PlatformCodeStub {
861 public:
862 explicit LoadIndexedInterceptorStub(Isolate* isolate)
863 : PlatformCodeStub(isolate) {}
864
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400865 Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; }
866 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867
868 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
869 DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
870};
871
872
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400873class LoadIndexedStringStub : public PlatformCodeStub {
874 public:
875 explicit LoadIndexedStringStub(Isolate* isolate)
876 : PlatformCodeStub(isolate) {}
877
878 Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; }
879 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
880
881 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
882 DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
883};
884
885
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000886class HandlerStub : public HydrogenCodeStub {
887 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400888 Code::Kind GetCodeKind() const OVERRIDE { return Code::HANDLER; }
889 ExtraICState GetExtraICState() const OVERRIDE { return kind(); }
890 InlineCacheState GetICState() const OVERRIDE { return MONOMORPHIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892 void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400894 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895
896 protected:
897 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
898
899 virtual Code::Kind kind() const = 0;
900
901 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
902};
903
904
905class LoadFieldStub: public HandlerStub {
906 public:
907 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
908 int property_index_key = index.GetFieldAccessStubKey();
909 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
910 }
911
912 FieldIndex index() const {
913 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
914 return FieldIndex::FromFieldAccessStubKey(property_index_key);
915 }
916
917 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400918 Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; }
919 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920
921 private:
922 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
923
924 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
925};
926
927
928class KeyedLoadSloppyArgumentsStub : public HandlerStub {
929 public:
930 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
931 : HandlerStub(isolate) {}
932
933 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400934 Code::Kind kind() const OVERRIDE { return Code::KEYED_LOAD_IC; }
935 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936
937 private:
938 DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
939};
940
941
942class LoadConstantStub : public HandlerStub {
943 public:
944 LoadConstantStub(Isolate* isolate, int constant_index)
945 : HandlerStub(isolate) {
946 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
947 }
948
949 int constant_index() const {
950 return ConstantIndexBits::decode(sub_minor_key());
951 }
952
953 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400954 Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; }
955 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956
957 private:
958 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
959
960 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
961};
962
963
964class StringLengthStub: public HandlerStub {
965 public:
966 explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
967
968 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400969 Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; }
970 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971
972 DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
973};
974
975
976class StoreFieldStub : public HandlerStub {
977 public:
978 StoreFieldStub(Isolate* isolate, FieldIndex index,
979 Representation representation)
980 : HandlerStub(isolate) {
981 int property_index_key = index.GetFieldAccessStubKey();
982 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
983 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
984 RepresentationBits::encode(repr));
985 }
986
987 FieldIndex index() const {
988 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
989 return FieldIndex::FromFieldAccessStubKey(property_index_key);
990 }
991
992 Representation representation() {
993 uint8_t repr = RepresentationBits::decode(sub_minor_key());
994 return PropertyDetails::DecodeRepresentation(repr);
995 }
996
997 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400998 Code::Kind kind() const OVERRIDE { return Code::STORE_IC; }
999 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000
1001 private:
1002 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1003 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1004
1005 DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1006};
1007
1008
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001009class StoreTransitionStub : public HandlerStub {
1010 public:
1011 enum StoreMode {
1012 StoreMapOnly,
1013 StoreMapAndValue,
1014 ExtendStorageAndStoreMapAndValue
1015 };
1016
1017 explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
1018 set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
1019 }
1020
1021 StoreTransitionStub(Isolate* isolate, FieldIndex index,
1022 Representation representation, StoreMode store_mode)
1023 : HandlerStub(isolate) {
1024 DCHECK(store_mode != StoreMapOnly);
1025 int property_index_key = index.GetFieldAccessStubKey();
1026 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1027 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1028 RepresentationBits::encode(repr) |
1029 StoreModeBits::encode(store_mode));
1030 }
1031
1032 FieldIndex index() const {
1033 DCHECK(store_mode() != StoreMapOnly);
1034 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1035 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1036 }
1037
1038 Representation representation() {
1039 DCHECK(store_mode() != StoreMapOnly);
1040 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1041 return PropertyDetails::DecodeRepresentation(repr);
1042 }
1043
1044 StoreMode store_mode() const {
1045 return StoreModeBits::decode(sub_minor_key());
1046 }
1047
1048 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
1049
1050 protected:
1051 Code::Kind kind() const OVERRIDE { return Code::STORE_IC; }
1052 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
1053
1054 private:
1055 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1056 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1057 class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1058
1059 DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1060};
1061
1062
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063class StoreGlobalStub : public HandlerStub {
1064 public:
1065 StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1066 : HandlerStub(isolate) {
1067 set_sub_minor_key(IsConstantBits::encode(is_constant) |
1068 CheckGlobalBits::encode(check_global));
1069 }
1070
1071 static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1072 return isolate->factory()->uninitialized_value();
1073 }
1074
1075 Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1076 Handle<PropertyCell> cell) {
1077 if (check_global()) {
1078 Code::FindAndReplacePattern pattern;
1079 pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1080 pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1081 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1082 return CodeStub::GetCodeCopy(pattern);
1083 } else {
1084 Code::FindAndReplacePattern pattern;
1085 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1086 return CodeStub::GetCodeCopy(pattern);
1087 }
1088 }
1089
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001090 Code::Kind kind() const OVERRIDE { return Code::STORE_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001091
1092 bool is_constant() const { return IsConstantBits::decode(sub_minor_key()); }
1093
1094 bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1095
1096 void set_is_constant(bool value) {
1097 set_sub_minor_key(IsConstantBits::update(sub_minor_key(), value));
1098 }
1099
1100 Representation representation() {
1101 return Representation::FromKind(
1102 RepresentationBits::decode(sub_minor_key()));
1103 }
1104
1105 void set_representation(Representation r) {
1106 set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1107 }
1108
1109 private:
1110 class IsConstantBits: public BitField<bool, 0, 1> {};
1111 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1112 class CheckGlobalBits: public BitField<bool, 9, 1> {};
1113
1114 DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1115};
1116
1117
1118class CallApiFunctionStub : public PlatformCodeStub {
1119 public:
1120 CallApiFunctionStub(Isolate* isolate,
1121 bool is_store,
1122 bool call_data_undefined,
1123 int argc) : PlatformCodeStub(isolate) {
1124 minor_key_ = IsStoreBits::encode(is_store) |
1125 CallDataUndefinedBits::encode(call_data_undefined) |
1126 ArgumentBits::encode(argc);
1127 DCHECK(!is_store || argc == 1);
1128 }
1129
1130 private:
1131 bool is_store() const { return IsStoreBits::decode(minor_key_); }
1132 bool call_data_undefined() const {
1133 return CallDataUndefinedBits::decode(minor_key_);
1134 }
1135 int argc() const { return ArgumentBits::decode(minor_key_); }
1136
1137 class IsStoreBits: public BitField<bool, 0, 1> {};
1138 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1139 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1140 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1141
1142 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1143 DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1144};
1145
1146
1147class CallApiGetterStub : public PlatformCodeStub {
1148 public:
1149 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1150
1151 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1152 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1153};
1154
1155
1156class BinaryOpICStub : public HydrogenCodeStub {
1157 public:
1158 BinaryOpICStub(Isolate* isolate, Token::Value op,
1159 OverwriteMode mode = NO_OVERWRITE)
1160 : HydrogenCodeStub(isolate, UNINITIALIZED) {
1161 BinaryOpICState state(isolate, op, mode);
1162 set_sub_minor_key(state.GetExtraICState());
1163 }
1164
1165 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1166 : HydrogenCodeStub(isolate) {
1167 set_sub_minor_key(state.GetExtraICState());
1168 }
1169
1170 static void GenerateAheadOfTime(Isolate* isolate);
1171
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001172 Code::Kind GetCodeKind() const OVERRIDE { return Code::BINARY_OP_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001174 InlineCacheState GetICState() const FINAL { return state().GetICState(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001175
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001176 ExtraICState GetExtraICState() const FINAL {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 return static_cast<ExtraICState>(sub_minor_key());
1178 }
1179
1180 BinaryOpICState state() const {
1181 return BinaryOpICState(isolate(), GetExtraICState());
1182 }
1183
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001184 void PrintState(std::ostream& os) const FINAL; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001185
1186 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1187 static const int kLeft = 0;
1188 static const int kRight = 1;
1189
1190 private:
1191 static void GenerateAheadOfTime(Isolate* isolate,
1192 const BinaryOpICState& state);
1193
1194 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1195 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1196};
1197
1198
1199// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1200// call support for stubs in Hydrogen.
1201class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub {
1202 public:
1203 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1204 const BinaryOpICState& state)
1205 : PlatformCodeStub(isolate) {
1206 minor_key_ = state.GetExtraICState();
1207 }
1208
1209 static void GenerateAheadOfTime(Isolate* isolate);
1210
1211 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1212 Code::FindAndReplacePattern pattern;
1213 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1214 return CodeStub::GetCodeCopy(pattern);
1215 }
1216
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001217 Code::Kind GetCodeKind() const OVERRIDE { return Code::BINARY_OP_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001218
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001219 InlineCacheState GetICState() const OVERRIDE { return state().GetICState(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 ExtraICState GetExtraICState() const OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001222 return static_cast<ExtraICState>(minor_key_);
1223 }
1224
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001225 void PrintState(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226
1227 private:
1228 BinaryOpICState state() const {
1229 return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1230 }
1231
1232 static void GenerateAheadOfTime(Isolate* isolate,
1233 const BinaryOpICState& state);
1234
1235 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1236 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1237};
1238
1239
1240class BinaryOpWithAllocationSiteStub FINAL : public BinaryOpICStub {
1241 public:
1242 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1243 Token::Value op,
1244 OverwriteMode mode)
1245 : BinaryOpICStub(isolate, op, mode) {}
1246
1247 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1248 : BinaryOpICStub(isolate, state) {}
1249
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001250 Code::Kind GetCodeKind() const FINAL { return Code::STUB; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251
1252 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1253 static const int kAllocationSite = 0;
1254 static const int kLeft = 1;
1255 static const int kRight = 2;
1256
1257 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1258 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1259};
1260
1261
1262enum StringAddFlags {
1263 // Omit both parameter checks.
1264 STRING_ADD_CHECK_NONE = 0,
1265 // Check left parameter.
1266 STRING_ADD_CHECK_LEFT = 1 << 0,
1267 // Check right parameter.
1268 STRING_ADD_CHECK_RIGHT = 1 << 1,
1269 // Check both parameters.
1270 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1271};
1272
1273
1274class StringAddStub FINAL : public HydrogenCodeStub {
1275 public:
1276 StringAddStub(Isolate* isolate, StringAddFlags flags,
1277 PretenureFlag pretenure_flag)
1278 : HydrogenCodeStub(isolate) {
1279 set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1280 PretenureFlagBits::encode(pretenure_flag));
1281 }
1282
1283 StringAddFlags flags() const {
1284 return StringAddFlagsBits::decode(sub_minor_key());
1285 }
1286
1287 PretenureFlag pretenure_flag() const {
1288 return PretenureFlagBits::decode(sub_minor_key());
1289 }
1290
1291 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1292 static const int kLeft = 0;
1293 static const int kRight = 1;
1294
1295 private:
1296 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1297 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1298
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001299 void PrintBaseName(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300
1301 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1302 DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1303};
1304
1305
1306class CompareICStub : public PlatformCodeStub {
1307 public:
1308 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1309 CompareICState::State right, CompareICState::State state)
1310 : PlatformCodeStub(isolate) {
1311 DCHECK(Token::IsCompareOp(op));
1312 minor_key_ = OpBits::encode(op - Token::EQ) | LeftStateBits::encode(left) |
1313 RightStateBits::encode(right) | StateBits::encode(state);
1314 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001315
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001316 void set_known_map(Handle<Map> map) { known_map_ = map; }
1317
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001318 InlineCacheState GetICState() const OVERRIDE;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001319
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320 Token::Value op() const {
1321 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001322 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001323
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 CompareICState::State left() const {
1325 return LeftStateBits::decode(minor_key_);
1326 }
1327 CompareICState::State right() const {
1328 return RightStateBits::decode(minor_key_);
1329 }
1330 CompareICState::State state() const { return StateBits::decode(minor_key_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001331
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001333 Code::Kind GetCodeKind() const OVERRIDE { return Code::COMPARE_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001334
1335 void GenerateSmis(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001336 void GenerateNumbers(MacroAssembler* masm);
1337 void GenerateInternalizedStrings(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00001338 void GenerateStrings(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 void GenerateUniqueNames(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001340 void GenerateObjects(MacroAssembler* masm);
1341 void GenerateMiss(MacroAssembler* masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001342 void GenerateKnownObjects(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001343 void GenerateGeneric(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001344
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345 bool strict() const { return op() == Token::EQ_STRICT; }
1346 Condition GetCondition() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001347
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001348 void AddToSpecialCache(Handle<Code> new_object) OVERRIDE;
1349 bool FindCodeInSpecialCache(Code** code_out) OVERRIDE;
1350 bool UseSpecialCache() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351 return state() == CompareICState::KNOWN_OBJECT;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001352 }
1353
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 class OpBits : public BitField<int, 0, 3> {};
1355 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1356 class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1357 class StateBits : public BitField<CompareICState::State, 11, 4> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001358
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359 Handle<Map> known_map_;
1360
1361 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1362 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001363};
1364
1365
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366class CompareNilICStub : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001367 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1369 Type* GetInputType(Zone* zone, Handle<Map> map);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001370
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001371 CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1372 set_sub_minor_key(NilValueBits::encode(nil));
1373 }
1374
1375 CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1376 InitializationState init_state = INITIALIZED)
1377 : HydrogenCodeStub(isolate, init_state) {
1378 set_sub_minor_key(ic_state);
1379 }
1380
1381 static Handle<Code> GetUninitialized(Isolate* isolate,
1382 NilValue nil) {
1383 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1384 }
1385
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001386 InlineCacheState GetICState() const OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 State state = this->state();
1388 if (state.Contains(GENERIC)) {
1389 return MEGAMORPHIC;
1390 } else if (state.Contains(MONOMORPHIC_MAP)) {
1391 return MONOMORPHIC;
1392 } else {
1393 return PREMONOMORPHIC;
1394 }
1395 }
1396
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001397 Code::Kind GetCodeKind() const OVERRIDE { return Code::COMPARE_NIL_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001399 ExtraICState GetExtraICState() const OVERRIDE { return sub_minor_key(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400
1401 void UpdateStatus(Handle<Object> object);
1402
1403 bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1404
1405 NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1406
1407 void ClearState() {
1408 set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1409 }
1410
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001411 void PrintState(std::ostream& os) const OVERRIDE; // NOLINT
1412 void PrintBaseName(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413
1414 private:
1415 CompareNilICStub(Isolate* isolate, NilValue nil,
1416 InitializationState init_state)
1417 : HydrogenCodeStub(isolate, init_state) {
1418 set_sub_minor_key(NilValueBits::encode(nil));
1419 }
1420
1421 enum CompareNilType {
1422 UNDEFINED,
1423 NULL_TYPE,
1424 MONOMORPHIC_MAP,
1425 GENERIC,
1426 NUMBER_OF_TYPES
1427 };
1428
1429 // At most 6 different types can be distinguished, because the Code object
1430 // only has room for a single byte to hold a set and there are two more
1431 // boolean flags we need to store. :-P
1432 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1433
1434 class State : public EnumSet<CompareNilType, byte> {
1435 public:
1436 State() : EnumSet<CompareNilType, byte>(0) { }
1437 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1438 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001439 friend std::ostream& operator<<(std::ostream& os, const State& s);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001440
1441 State state() const { return State(TypesBits::decode(sub_minor_key())); }
1442
1443 class NilValueBits : public BitField<NilValue, 0, 1> {};
1444 class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1445
1446 friend class CompareNilIC;
1447
1448 DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1449 DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1450};
1451
1452
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001453std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001454
1455
1456class CEntryStub : public PlatformCodeStub {
1457 public:
1458 CEntryStub(Isolate* isolate, int result_size,
1459 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1460 : PlatformCodeStub(isolate) {
1461 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1462 DCHECK(result_size == 1 || result_size == 2);
1463#ifdef _WIN64
1464 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1465#endif // _WIN64
1466 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001467
1468 // The version of this stub that doesn't save doubles is generated ahead of
1469 // time, so it's OK to call it from other stubs that can't cope with GC during
1470 // their code generation. On machines that always have gp registers (x64) we
1471 // can generate both variants ahead of time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 static void GenerateAheadOfTime(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001473
1474 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001475 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1476#ifdef _WIN64
1477 int result_size() const { return ResultSizeBits::decode(minor_key_); }
1478#endif // _WIN64
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001479
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001480 bool NeedsImmovableCode() OVERRIDE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001481
1482 class SaveDoublesBits : public BitField<bool, 0, 1> {};
1483 class ResultSizeBits : public BitField<int, 1, 3> {};
1484
1485 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1486 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001487};
1488
1489
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001490class JSEntryStub : public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001491 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001492 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1493 : PlatformCodeStub(isolate) {
1494 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1495 minor_key_ = StackFrameTypeBits::encode(type);
1496 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001497
1498 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001499 void FinishCode(Handle<Code> code) OVERRIDE;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001500
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001501 void PrintName(std::ostream& os) const OVERRIDE { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001502 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1503 : "JSConstructEntryStub");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001504 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001505
1506 StackFrame::Type type() const {
1507 return StackFrameTypeBits::decode(minor_key_);
1508 }
1509
1510 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1511
1512 int handler_offset_;
1513
1514 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1515 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001516};
1517
1518
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519class ArgumentsAccessStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001520 public:
1521 enum Type {
1522 READ_ELEMENT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523 NEW_SLOPPY_FAST,
1524 NEW_SLOPPY_SLOW,
Steve Block44f0eee2011-05-26 01:26:41 +01001525 NEW_STRICT
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001526 };
1527
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528 ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1529 minor_key_ = TypeBits::encode(type);
1530 }
1531
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001532 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533 if (type() == READ_ELEMENT) {
1534 return ArgumentsAccessReadDescriptor(isolate());
1535 }
1536 return ContextOnlyDescriptor(isolate());
1537 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001538
1539 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 Type type() const { return TypeBits::decode(minor_key_); }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001541
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001542 void GenerateReadElement(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001543 void GenerateNewStrict(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 void GenerateNewSloppyFast(MacroAssembler* masm);
1545 void GenerateNewSloppySlow(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001546
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001547 void PrintName(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001548
1549 class TypeBits : public BitField<Type, 0, 2> {};
1550
1551 DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001552};
1553
1554
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555class RegExpExecStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001556 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001557 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001559 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1560 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001561};
1562
1563
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001564class RegExpConstructResultStub FINAL : public HydrogenCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001565 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001566 explicit RegExpConstructResultStub(Isolate* isolate)
1567 : HydrogenCodeStub(isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001568
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1570 static const int kLength = 0;
1571 static const int kIndex = 1;
1572 static const int kInput = 2;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001573
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1575 DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001576};
1577
1578
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579class CallFunctionStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001580 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001581 CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1582 : PlatformCodeStub(isolate) {
1583 DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1584 minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001585 }
1586
Ben Murdoch086aeea2011-05-13 15:57:08 +01001587 static int ExtractArgcFromMinorKey(int minor_key) {
1588 return ArgcBits::decode(minor_key);
1589 }
1590
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001591 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001592 int argc() const { return ArgcBits::decode(minor_key_); }
1593 int flags() const { return FlagBits::decode(minor_key_); }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001594
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001595 bool CallAsMethod() const {
1596 return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1597 }
1598
1599 bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1600
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001601 void PrintName(std::ostream& os) const OVERRIDE; // NOLINT
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001602
1603 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001604 class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1605 class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1606 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001607
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001608 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1609 DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001610};
1611
1612
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613class CallConstructStub: public PlatformCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001614 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615 CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1616 : PlatformCodeStub(isolate) {
1617 minor_key_ = FlagBits::encode(flags);
1618 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001619
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001620 void FinishCode(Handle<Code> code) OVERRIDE {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001621 code->set_has_function_cache(RecordCallTarget());
1622 }
1623
1624 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001625 CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001626
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001627 bool RecordCallTarget() const {
1628 return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001629 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001630
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001631 void PrintName(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001632
1633 class FlagBits : public BitField<CallConstructorFlags, 0, 1> {};
1634
1635 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1636 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001637};
1638
1639
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001640enum StringIndexFlags {
1641 // Accepts smis or heap numbers.
1642 STRING_INDEX_IS_NUMBER,
1643
1644 // Accepts smis or heap numbers that are valid array indices
1645 // (ECMA-262 15.4). Invalid indices are reported as being out of
1646 // range.
1647 STRING_INDEX_IS_ARRAY_INDEX
1648};
1649
1650
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001651enum ReceiverCheckMode {
1652 // We don't know anything about the receiver.
1653 RECEIVER_IS_UNKNOWN,
1654
1655 // We know the receiver is a string.
1656 RECEIVER_IS_STRING
1657};
1658
1659
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001660// Generates code implementing String.prototype.charCodeAt.
1661//
1662// Only supports the case when the receiver is a string and the index
1663// is a number (smi or heap number) that is a valid index into the
1664// string. Additional index constraints are specified by the
1665// flags. Otherwise, bails out to the provided labels.
1666//
1667// Register usage: |object| may be changed to another string in a way
1668// that doesn't affect charCodeAt/charAt semantics, |index| is
1669// preserved, |scratch| and |result| are clobbered.
1670class StringCharCodeAtGenerator {
1671 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001672 StringCharCodeAtGenerator(Register object, Register index, Register result,
1673 Label* receiver_not_string, Label* index_not_number,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001674 Label* index_out_of_range,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001675 StringIndexFlags index_flags,
1676 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001677 : object_(object),
1678 index_(index),
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001679 result_(result),
1680 receiver_not_string_(receiver_not_string),
1681 index_not_number_(index_not_number),
1682 index_out_of_range_(index_out_of_range),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001683 index_flags_(index_flags),
1684 check_mode_(check_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001685 DCHECK(!result_.is(object_));
1686 DCHECK(!result_.is(index_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001687 }
1688
1689 // Generates the fast case code. On the fallthrough path |result|
1690 // register contains the result.
1691 void GenerateFast(MacroAssembler* masm);
1692
1693 // Generates the slow case code. Must not be naturally
1694 // reachable. Expected to be put after a ret instruction (e.g., in
1695 // deferred code). Always jumps back to the fast case.
1696 void GenerateSlow(MacroAssembler* masm,
1697 const RuntimeCallHelper& call_helper);
1698
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001699 // Skip handling slow case and directly jump to bailout.
1700 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1701 masm->bind(&index_not_smi_);
1702 masm->bind(&call_runtime_);
1703 masm->jmp(bailout);
1704 }
1705
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001706 private:
1707 Register object_;
1708 Register index_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001709 Register result_;
1710
1711 Label* receiver_not_string_;
1712 Label* index_not_number_;
1713 Label* index_out_of_range_;
1714
1715 StringIndexFlags index_flags_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001716 ReceiverCheckMode check_mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001717
1718 Label call_runtime_;
1719 Label index_not_smi_;
1720 Label got_smi_index_;
1721 Label exit_;
1722
1723 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1724};
1725
1726
1727// Generates code for creating a one-char string from a char code.
1728class StringCharFromCodeGenerator {
1729 public:
1730 StringCharFromCodeGenerator(Register code,
1731 Register result)
1732 : code_(code),
1733 result_(result) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734 DCHECK(!code_.is(result_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001735 }
1736
1737 // Generates the fast case code. On the fallthrough path |result|
1738 // register contains the result.
1739 void GenerateFast(MacroAssembler* masm);
1740
1741 // Generates the slow case code. Must not be naturally
1742 // reachable. Expected to be put after a ret instruction (e.g., in
1743 // deferred code). Always jumps back to the fast case.
1744 void GenerateSlow(MacroAssembler* masm,
1745 const RuntimeCallHelper& call_helper);
1746
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001747 // Skip handling slow case and directly jump to bailout.
1748 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1749 masm->bind(&slow_case_);
1750 masm->jmp(bailout);
1751 }
1752
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001753 private:
1754 Register code_;
1755 Register result_;
1756
1757 Label slow_case_;
1758 Label exit_;
1759
1760 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1761};
1762
1763
1764// Generates code implementing String.prototype.charAt.
1765//
1766// Only supports the case when the receiver is a string and the index
1767// is a number (smi or heap number) that is a valid index into the
1768// string. Additional index constraints are specified by the
1769// flags. Otherwise, bails out to the provided labels.
1770//
1771// Register usage: |object| may be changed to another string in a way
1772// that doesn't affect charCodeAt/charAt semantics, |index| is
1773// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1774class StringCharAtGenerator {
1775 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001776 StringCharAtGenerator(Register object, Register index, Register scratch,
1777 Register result, Label* receiver_not_string,
1778 Label* index_not_number, Label* index_out_of_range,
1779 StringIndexFlags index_flags,
1780 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
1781 : char_code_at_generator_(object, index, scratch, receiver_not_string,
1782 index_not_number, index_out_of_range,
1783 index_flags, check_mode),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001784 char_from_code_generator_(scratch, result) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001785
1786 // Generates the fast case code. On the fallthrough path |result|
1787 // register contains the result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001788 void GenerateFast(MacroAssembler* masm) {
1789 char_code_at_generator_.GenerateFast(masm);
1790 char_from_code_generator_.GenerateFast(masm);
1791 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001792
1793 // Generates the slow case code. Must not be naturally
1794 // reachable. Expected to be put after a ret instruction (e.g., in
1795 // deferred code). Always jumps back to the fast case.
1796 void GenerateSlow(MacroAssembler* masm,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001797 const RuntimeCallHelper& call_helper) {
1798 char_code_at_generator_.GenerateSlow(masm, call_helper);
1799 char_from_code_generator_.GenerateSlow(masm, call_helper);
1800 }
1801
1802 // Skip handling slow case and directly jump to bailout.
1803 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1804 char_code_at_generator_.SkipSlow(masm, bailout);
1805 char_from_code_generator_.SkipSlow(masm, bailout);
1806 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001807
1808 private:
1809 StringCharCodeAtGenerator char_code_at_generator_;
1810 StringCharFromCodeGenerator char_from_code_generator_;
1811
1812 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1813};
1814
Ben Murdoch086aeea2011-05-13 15:57:08 +01001815
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001816class LoadDictionaryElementStub : public HydrogenCodeStub {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001817 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001818 explicit LoadDictionaryElementStub(Isolate* isolate)
1819 : HydrogenCodeStub(isolate) {}
Ben Murdoch086aeea2011-05-13 15:57:08 +01001820
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001821 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
1822 if (FLAG_vector_ics) {
1823 return VectorLoadICDescriptor(isolate());
1824 }
1825 return LoadDescriptor(isolate());
1826 }
1827
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001829};
1830
Ben Murdoch257744e2011-11-30 15:57:28 +00001831
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001832class KeyedLoadGenericStub : public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00001833 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001834 explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdoch257744e2011-11-30 15:57:28 +00001835
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001836 Code::Kind GetCodeKind() const OVERRIDE { return Code::KEYED_LOAD_IC; }
1837 InlineCacheState GetICState() const OVERRIDE { return GENERIC; }
Ben Murdoch257744e2011-11-30 15:57:28 +00001838
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001839 // Since KeyedLoadGeneric stub doesn't miss (simply calls runtime), it
1840 // doesn't need to use the VectorLoadICDescriptor for the case when
1841 // flag --vector-ics is true.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001842 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001843
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001844 DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00001845};
1846
1847
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001848class LoadICTrampolineStub : public PlatformCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00001849 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001850 LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
1851 : PlatformCodeStub(isolate) {
1852 minor_key_ = state.GetExtraICState();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001853 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001854
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001855 Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001856
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001857 InlineCacheState GetICState() const FINAL { return DEFAULT; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001858
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001859 ExtraICState GetExtraICState() const FINAL {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001860 return static_cast<ExtraICState>(minor_key_);
1861 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001862
Ben Murdoch257744e2011-11-30 15:57:28 +00001863 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001864 LoadICState state() const {
1865 return LoadICState(static_cast<ExtraICState>(minor_key_));
1866 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001867
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadICTrampoline);
1869 DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00001870};
1871
1872
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
1874 public:
1875 explicit KeyedLoadICTrampolineStub(Isolate* isolate)
1876 : LoadICTrampolineStub(isolate, LoadICState(0)) {}
1877
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001878 Code::Kind GetCodeKind() const OVERRIDE { return Code::KEYED_LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001879
1880 DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
1881};
1882
1883
1884class MegamorphicLoadStub : public HydrogenCodeStub {
1885 public:
1886 MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
1887 : HydrogenCodeStub(isolate) {
1888 set_sub_minor_key(state.GetExtraICState());
1889 }
1890
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001891 Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001892
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001893 InlineCacheState GetICState() const FINAL { return MEGAMORPHIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001894
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001895 ExtraICState GetExtraICState() const FINAL {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001896 return static_cast<ExtraICState>(sub_minor_key());
1897 }
1898
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001899 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
1900 if (FLAG_vector_ics) {
1901 return VectorLoadICDescriptor(isolate());
1902 }
1903 return LoadDescriptor(isolate());
1904 }
1905
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001906 DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
1907};
1908
1909
1910class VectorLoadStub : public HydrogenCodeStub {
1911 public:
1912 explicit VectorLoadStub(Isolate* isolate, const LoadICState& state)
1913 : HydrogenCodeStub(isolate) {
1914 set_sub_minor_key(state.GetExtraICState());
1915 }
1916
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001917 Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001919 InlineCacheState GetICState() const FINAL { return DEFAULT; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001920
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001921 ExtraICState GetExtraICState() const FINAL {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922 return static_cast<ExtraICState>(sub_minor_key());
1923 }
1924
1925 private:
1926 LoadICState state() const { return LoadICState(GetExtraICState()); }
1927
1928 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1929 DEFINE_HYDROGEN_CODE_STUB(VectorLoad, HydrogenCodeStub);
1930};
1931
1932
1933class VectorKeyedLoadStub : public VectorLoadStub {
1934 public:
1935 explicit VectorKeyedLoadStub(Isolate* isolate)
1936 : VectorLoadStub(isolate, LoadICState(0)) {}
1937
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001938 Code::Kind GetCodeKind() const OVERRIDE { return Code::KEYED_LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001939
1940 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1941 DEFINE_HYDROGEN_CODE_STUB(VectorKeyedLoad, VectorLoadStub);
1942};
1943
1944
1945class DoubleToIStub : public PlatformCodeStub {
1946 public:
1947 DoubleToIStub(Isolate* isolate, Register source, Register destination,
1948 int offset, bool is_truncating, bool skip_fastpath = false)
1949 : PlatformCodeStub(isolate) {
1950 minor_key_ = SourceRegisterBits::encode(source.code()) |
1951 DestinationRegisterBits::encode(destination.code()) |
1952 OffsetBits::encode(offset) |
1953 IsTruncatingBits::encode(is_truncating) |
1954 SkipFastPathBits::encode(skip_fastpath) |
1955 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1956 }
1957
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001958 bool SometimesSetsUpAFrame() OVERRIDE { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001959
1960 private:
1961 Register source() const {
1962 return Register::from_code(SourceRegisterBits::decode(minor_key_));
1963 }
1964 Register destination() const {
1965 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
1966 }
1967 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
1968 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
1969 int offset() const { return OffsetBits::decode(minor_key_); }
1970
1971 static const int kBitsPerRegisterNumber = 6;
1972 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1973 class SourceRegisterBits:
1974 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1975 class DestinationRegisterBits:
1976 public BitField<int, kBitsPerRegisterNumber,
1977 kBitsPerRegisterNumber> {}; // NOLINT
1978 class IsTruncatingBits:
1979 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1980 class OffsetBits:
1981 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1982 class SkipFastPathBits:
1983 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1984 class SSE3Bits:
1985 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
1986
1987 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1988 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
1989};
1990
1991
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001992class ScriptContextFieldStub : public HandlerStub {
1993 public:
1994 ScriptContextFieldStub(Isolate* isolate,
1995 const ScriptContextTable::LookupResult* lookup_result)
1996 : HandlerStub(isolate) {
1997 DCHECK(Accepted(lookup_result));
1998 set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
1999 SlotIndexBits::encode(lookup_result->slot_index));
2000 }
2001
2002 int context_index() const {
2003 return ContextIndexBits::decode(sub_minor_key());
2004 }
2005
2006 int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2007
2008 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2009 return ContextIndexBits::is_valid(lookup_result->context_index) &&
2010 SlotIndexBits::is_valid(lookup_result->slot_index);
2011 }
2012
2013 private:
2014 static const int kContextIndexBits = 13;
2015 static const int kSlotIndexBits = 13;
2016 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2017 class SlotIndexBits
2018 : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2019
2020 Code::StubType GetStubType() OVERRIDE { return Code::FAST; }
2021
2022 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2023};
2024
2025
2026class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2027 public:
2028 LoadScriptContextFieldStub(
2029 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2030 : ScriptContextFieldStub(isolate, lookup_result) {}
2031
2032 private:
2033 Code::Kind kind() const OVERRIDE { return Code::LOAD_IC; }
2034
2035 DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2036};
2037
2038
2039class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2040 public:
2041 StoreScriptContextFieldStub(
2042 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2043 : ScriptContextFieldStub(isolate, lookup_result) {}
2044
2045 private:
2046 Code::Kind kind() const OVERRIDE { return Code::STORE_IC; }
2047
2048 DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2049};
2050
2051
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002052class LoadFastElementStub : public HydrogenCodeStub {
2053 public:
2054 LoadFastElementStub(Isolate* isolate, bool is_js_array,
2055 ElementsKind elements_kind)
2056 : HydrogenCodeStub(isolate) {
2057 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
2058 IsJSArrayBits::encode(is_js_array));
2059 }
2060
2061 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2062
2063 ElementsKind elements_kind() const {
2064 return ElementsKindBits::decode(sub_minor_key());
2065 }
2066
2067 private:
2068 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2069 class IsJSArrayBits: public BitField<bool, 8, 1> {};
2070
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002071 CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
2072 if (FLAG_vector_ics) {
2073 return VectorLoadICDescriptor(isolate());
2074 }
2075 return LoadDescriptor(isolate());
2076 }
2077
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002078 DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
2079};
2080
2081
2082class StoreFastElementStub : public HydrogenCodeStub {
2083 public:
2084 StoreFastElementStub(Isolate* isolate, bool is_js_array,
2085 ElementsKind elements_kind, KeyedAccessStoreMode mode)
2086 : HydrogenCodeStub(isolate) {
2087 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
2088 IsJSArrayBits::encode(is_js_array) |
2089 StoreModeBits::encode(mode));
2090 }
2091
2092 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2093
2094 ElementsKind elements_kind() const {
2095 return ElementsKindBits::decode(sub_minor_key());
2096 }
2097
2098 KeyedAccessStoreMode store_mode() const {
2099 return StoreModeBits::decode(sub_minor_key());
2100 }
2101
2102 private:
2103 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2104 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2105 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2106
2107 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2108 DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2109};
2110
2111
2112class TransitionElementsKindStub : public HydrogenCodeStub {
2113 public:
2114 TransitionElementsKindStub(Isolate* isolate,
2115 ElementsKind from_kind,
2116 ElementsKind to_kind,
2117 bool is_js_array) : HydrogenCodeStub(isolate) {
2118 set_sub_minor_key(FromKindBits::encode(from_kind) |
2119 ToKindBits::encode(to_kind) |
2120 IsJSArrayBits::encode(is_js_array));
2121 }
2122
2123 ElementsKind from_kind() const {
2124 return FromKindBits::decode(sub_minor_key());
2125 }
2126
2127 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2128
2129 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2130
2131 private:
2132 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2133 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2134 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2135
2136 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2137 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2138};
2139
2140
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002141class AllocateHeapNumberStub FINAL : public HydrogenCodeStub {
2142 public:
2143 explicit AllocateHeapNumberStub(Isolate* isolate)
2144 : HydrogenCodeStub(isolate) {}
2145
2146 private:
2147 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2148 DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2149};
2150
2151
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002152class ArrayConstructorStubBase : public HydrogenCodeStub {
2153 public:
2154 ArrayConstructorStubBase(Isolate* isolate,
2155 ElementsKind kind,
2156 AllocationSiteOverrideMode override_mode)
2157 : HydrogenCodeStub(isolate) {
2158 // It only makes sense to override local allocation site behavior
2159 // if there is a difference between the global allocation site policy
2160 // for an ElementsKind and the desired usage of the stub.
2161 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2162 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2163 set_sub_minor_key(ElementsKindBits::encode(kind) |
2164 AllocationSiteOverrideModeBits::encode(override_mode));
2165 }
2166
2167 ElementsKind elements_kind() const {
2168 return ElementsKindBits::decode(sub_minor_key());
2169 }
2170
2171 AllocationSiteOverrideMode override_mode() const {
2172 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2173 }
2174
2175 static void GenerateStubsAheadOfTime(Isolate* isolate);
2176
2177 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2178 static const int kConstructor = 0;
2179 static const int kAllocationSite = 1;
2180
2181 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002182 std::ostream& BasePrintName(std::ostream& os,
2183 const char* name) const; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002184
2185 private:
2186 // Ensure data fits within available bits.
2187 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2188
2189 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2190 class AllocationSiteOverrideModeBits: public
2191 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2192
2193 DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2194};
2195
2196
2197class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2198 public:
2199 ArrayNoArgumentConstructorStub(
2200 Isolate* isolate,
2201 ElementsKind kind,
2202 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2203 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2204 }
2205
2206 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002207 void PrintName(std::ostream& os) const OVERRIDE { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002208 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2209 }
2210
2211 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2212 DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2213 ArrayConstructorStubBase);
2214};
2215
2216
2217class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2218 public:
2219 ArraySingleArgumentConstructorStub(
2220 Isolate* isolate,
2221 ElementsKind kind,
2222 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2223 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2224 }
2225
2226 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002227 void PrintName(std::ostream& os) const OVERRIDE { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002228 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2229 }
2230
2231 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2232 DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2233 ArrayConstructorStubBase);
2234};
2235
2236
2237class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2238 public:
2239 ArrayNArgumentsConstructorStub(
2240 Isolate* isolate,
2241 ElementsKind kind,
2242 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2243 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2244 }
2245
2246 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002247 void PrintName(std::ostream& os) const OVERRIDE { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2249 }
2250
2251 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2252 DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2253 ArrayConstructorStubBase);
2254};
2255
2256
2257class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2258 public:
2259 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2260 : HydrogenCodeStub(isolate) {
2261 set_sub_minor_key(ElementsKindBits::encode(kind));
2262 }
2263
2264 static void GenerateStubsAheadOfTime(Isolate* isolate);
2265
2266 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2267 static const int kConstructor = 0;
2268
2269 ElementsKind elements_kind() const {
2270 return ElementsKindBits::decode(sub_minor_key());
2271 }
2272
2273 private:
2274 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2275
2276 DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2277};
2278
2279
2280class InternalArrayNoArgumentConstructorStub : public
2281 InternalArrayConstructorStubBase {
2282 public:
2283 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2284 ElementsKind kind)
2285 : InternalArrayConstructorStubBase(isolate, kind) { }
2286
2287 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2288 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2289 InternalArrayConstructorStubBase);
2290};
2291
2292
2293class InternalArraySingleArgumentConstructorStub : public
2294 InternalArrayConstructorStubBase {
2295 public:
2296 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2297 ElementsKind kind)
2298 : InternalArrayConstructorStubBase(isolate, kind) { }
2299
2300 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2301 DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2302 InternalArrayConstructorStubBase);
2303};
2304
2305
2306class InternalArrayNArgumentsConstructorStub : public
2307 InternalArrayConstructorStubBase {
2308 public:
2309 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2310 : InternalArrayConstructorStubBase(isolate, kind) { }
2311
2312 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2313 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2314 InternalArrayConstructorStubBase);
2315};
2316
2317
2318class StoreElementStub : public PlatformCodeStub {
2319 public:
2320 StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2321 : PlatformCodeStub(isolate) {
2322 minor_key_ = ElementsKindBits::encode(elements_kind);
2323 }
2324
2325 private:
2326 ElementsKind elements_kind() const {
2327 return ElementsKindBits::decode(minor_key_);
2328 }
2329
2330 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2331
2332 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2333 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2334};
2335
2336
2337class ToBooleanStub: public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002338 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002339 enum Type {
2340 UNDEFINED,
2341 BOOLEAN,
2342 NULL_TYPE,
2343 SMI,
2344 SPEC_OBJECT,
2345 STRING,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002346 SYMBOL,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002347 HEAP_NUMBER,
2348 NUMBER_OF_TYPES
2349 };
2350
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002351 enum ResultMode {
2352 RESULT_AS_SMI, // For Smi(1) on truthy value, Smi(0) otherwise.
2353 RESULT_AS_ODDBALL, // For {true} on truthy value, {false} otherwise.
2354 RESULT_AS_INVERSE_ODDBALL // For {false} on truthy value, {true} otherwise.
2355 };
2356
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002357 // At most 8 different types can be distinguished, because the Code object
2358 // only has room for a single byte to hold a set of these types. :-P
2359 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2360
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002361 class Types : public EnumSet<Type, byte> {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002362 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002363 Types() : EnumSet<Type, byte>(0) {}
2364 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002365
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002366 byte ToByte() const { return ToIntegral(); }
2367 bool UpdateStatus(Handle<Object> object);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002368 bool NeedsMap() const;
2369 bool CanBeUndetectable() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002370 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002371
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002372 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002373 };
2374
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002375 ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2376 : HydrogenCodeStub(isolate) {
2377 set_sub_minor_key(TypesBits::encode(types.ToByte()) |
2378 ResultModeBits::encode(mode));
2379 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002380
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002381 ToBooleanStub(Isolate* isolate, ExtraICState state)
2382 : HydrogenCodeStub(isolate) {
2383 set_sub_minor_key(TypesBits::encode(static_cast<byte>(state)) |
2384 ResultModeBits::encode(RESULT_AS_SMI));
2385 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002386
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002387 bool UpdateStatus(Handle<Object> object);
2388 Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2389 ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2390
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002391 Code::Kind GetCodeKind() const OVERRIDE { return Code::TO_BOOLEAN_IC; }
2392 void PrintState(std::ostream& os) const OVERRIDE; // NOLINT
Ben Murdoch257744e2011-11-30 15:57:28 +00002393
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002394 bool SometimesSetsUpAFrame() OVERRIDE { return false; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002395
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002396 static Handle<Code> GetUninitialized(Isolate* isolate) {
2397 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002398 }
2399
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002400 ExtraICState GetExtraICState() const OVERRIDE { return types().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002401
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002402 InlineCacheState GetICState() const OVERRIDE {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002403 if (types().IsEmpty()) {
2404 return ::v8::internal::UNINITIALIZED;
2405 } else {
2406 return MONOMORPHIC;
2407 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002408 }
2409
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002410 private:
2411 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2412 : HydrogenCodeStub(isolate, init_state) {
2413 set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2414 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002415
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002416 class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2417 class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002418
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002419 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2420 DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002421};
2422
2423
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002424std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002425
2426
2427class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002428 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002429 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2430 ElementsKind to_kind, bool is_jsarray,
2431 KeyedAccessStoreMode store_mode)
2432 : HydrogenCodeStub(isolate) {
2433 set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2434 IsJSArrayBits::encode(is_jsarray) |
2435 StoreModeBits::encode(store_mode));
2436 }
2437
2438 ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2439 ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2440 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2441 KeyedAccessStoreMode store_mode() const {
2442 return StoreModeBits::decode(sub_minor_key());
2443 }
2444
2445 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2446 enum ParameterIndices {
2447 kValueIndex,
2448 kMapIndex,
2449 kKeyIndex,
2450 kObjectIndex,
2451 kParameterCount
2452 };
2453
2454 static const Register ValueRegister() {
2455 return ElementTransitionAndStoreDescriptor::ValueRegister();
2456 }
2457 static const Register MapRegister() {
2458 return ElementTransitionAndStoreDescriptor::MapRegister();
2459 }
2460 static const Register KeyRegister() {
2461 return ElementTransitionAndStoreDescriptor::NameRegister();
2462 }
2463 static const Register ObjectRegister() {
2464 return ElementTransitionAndStoreDescriptor::ReceiverRegister();
2465 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002466
2467 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002468 class FromBits : public BitField<ElementsKind, 0, 8> {};
2469 class ToBits : public BitField<ElementsKind, 8, 8> {};
2470 class IsJSArrayBits : public BitField<bool, 16, 1> {};
2471 class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002473 DEFINE_CALL_INTERFACE_DESCRIPTOR(ElementTransitionAndStore);
2474 DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002475};
2476
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002477
2478class StoreArrayLiteralElementStub : public PlatformCodeStub {
2479 public:
2480 explicit StoreArrayLiteralElementStub(Isolate* isolate)
2481 : PlatformCodeStub(isolate) { }
2482
2483 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2484 DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2485};
2486
2487
2488class StubFailureTrampolineStub : public PlatformCodeStub {
2489 public:
2490 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2491 : PlatformCodeStub(isolate) {
2492 minor_key_ = FunctionModeField::encode(function_mode);
2493 }
2494
2495 static void GenerateAheadOfTime(Isolate* isolate);
2496
2497 private:
2498 StubFunctionMode function_mode() const {
2499 return FunctionModeField::decode(minor_key_);
2500 }
2501
2502 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2503
2504 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2505 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2506};
2507
2508
2509class ProfileEntryHookStub : public PlatformCodeStub {
2510 public:
2511 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2512
2513 // The profile entry hook function is not allowed to cause a GC.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002514 bool SometimesSetsUpAFrame() OVERRIDE { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002515
2516 // Generates a call to the entry hook if it's enabled.
2517 static void MaybeCallEntryHook(MacroAssembler* masm);
2518
2519 private:
2520 static void EntryHookTrampoline(intptr_t function,
2521 intptr_t stack_pointer,
2522 Isolate* isolate);
2523
2524 // ProfileEntryHookStub is called at the start of a function, so it has the
2525 // same register set.
2526 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2527 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2528};
2529
2530
2531class StoreBufferOverflowStub : public PlatformCodeStub {
2532 public:
2533 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2534 : PlatformCodeStub(isolate) {
2535 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2536 }
2537
2538 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002539 bool SometimesSetsUpAFrame() OVERRIDE { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002540
2541 private:
2542 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2543
2544 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2545
2546 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2547 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2548};
2549
2550
2551class SubStringStub : public PlatformCodeStub {
2552 public:
2553 explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2554
2555 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2556 DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2557};
2558
2559
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002560class ToNumberStub FINAL : public PlatformCodeStub {
2561 public:
2562 explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2563
2564 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
2565 DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
2566};
2567
2568
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002569class StringCompareStub : public PlatformCodeStub {
2570 public:
2571 explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2572
2573 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2574 DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2575};
2576
2577
2578#undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2579#undef DEFINE_PLATFORM_CODE_STUB
2580#undef DEFINE_HANDLER_CODE_STUB
2581#undef DEFINE_HYDROGEN_CODE_STUB
2582#undef DEFINE_CODE_STUB
2583#undef DEFINE_CODE_STUB_BASE
Steve Blocka7e24c12009-10-30 11:49:00 +00002584} } // namespace v8::internal
2585
2586#endif // V8_CODE_STUBS_H_