1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
6
// * Redistributions of source code must retain the above copyright
7
// notice, this list of conditions and the following disclaimer.
8
// * Redistributions in binary form must reproduce the above
9
// copyright notice, this list of conditions and the following
10
// disclaimer in the documentation and/or other materials provided
11
// with the distribution.
12
// * Neither the name of Google Inc. nor the names of its
13
// contributors may be used to endorse or promote products derived
14
// from this software without specific prior written permission.
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
#include "macro-assembler.h"
32
#include "type-info.h"
38
// IC_UTIL_LIST defines all utility functions called from generated
39
// inline caching code. The argument for the macro, ICU, is the function name.
40
#define IC_UTIL_LIST(ICU) \
42
ICU(KeyedLoadIC_Miss) \
43
ICU(KeyedLoadIC_MissForceGeneric) \
45
ICU(KeyedCallIC_Miss) \
47
ICU(StoreIC_ArrayLength) \
48
ICU(SharedStoreIC_ExtendStorage) \
49
ICU(KeyedStoreIC_Miss) \
50
ICU(KeyedStoreIC_MissForceGeneric) \
51
ICU(KeyedStoreIC_Slow) \
52
/* Utilities for IC stubs. */ \
53
ICU(LoadCallbackProperty) \
54
ICU(StoreCallbackProperty) \
55
ICU(LoadPropertyWithInterceptorOnly) \
56
ICU(LoadPropertyWithInterceptorForLoad) \
57
ICU(LoadPropertyWithInterceptorForCall) \
58
ICU(KeyedLoadPropertyWithInterceptor) \
59
ICU(StoreInterceptorProperty) \
65
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
70
// The ids for utility called from the generated code.
72
#define CONST_NAME(name) k##name,
73
IC_UTIL_LIST(CONST_NAME)
78
// Looks up the address of the named utility.
79
static Address AddressFromUtilityId(UtilityId id);
81
// Alias the inline cache state type to make the IC code more readable.
82
typedef InlineCacheState State;
84
// The IC code is either invoked with no extra frames on the stack
85
// or with a single extra frame for supporting calls.
91
// Construct the IC structure with the given number of extra
92
// JavaScript frames on the stack.
93
IC(FrameDepth depth, Isolate* isolate);
96
// Get the call-site target; used for determining the state.
97
Code* target() const { return GetTargetAtAddress(address()); }
98
inline Address address() const;
100
virtual bool IsGeneric() const { return false; }
102
// Compute the current IC state based on the target stub, receiver and name.
103
static State StateFrom(Code* target, Object* receiver, Object* name);
105
// Clear the inline cache to initial state.
106
static void Clear(Address address);
108
// Computes the reloc info for this IC. This is a fairly expensive
109
// operation as it has to search through the heap to find the code
110
// object that contains this IC site.
111
RelocInfo::Mode ComputeMode();
113
// Returns if this IC is for contextual (no explicit receiver)
114
// access to properties.
115
bool IsContextual(Handle<Object> receiver) {
116
if (receiver->IsGlobalObject()) {
117
return SlowIsContextual();
119
ASSERT(!SlowIsContextual());
124
bool SlowIsContextual() {
125
return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
128
// Determines which map must be used for keeping the code stub.
129
// These methods should not be called with undefined or null.
130
static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
132
static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
134
static inline JSObject* GetCodeCacheHolder(Object* object,
135
InlineCacheHolderFlag holder);
138
Address fp() const { return fp_; }
139
Address pc() const { return *pc_address_; }
140
Isolate* isolate() const { return isolate_; }
142
#ifdef ENABLE_DEBUGGER_SUPPORT
143
// Computes the address in the original code when the code running is
144
// containing break points (calls to DebugBreakXXX builtins).
145
Address OriginalCodeAddress() const;
148
// Set the call-site target.
149
void set_target(Code* code) { SetTargetAtAddress(address(), code); }
152
char TransitionMarkFromState(IC::State state);
154
void TraceIC(const char* type,
160
Failure* TypeError(const char* type,
161
Handle<Object> object,
163
Failure* ReferenceError(const char* type, Handle<String> name);
165
// Access the target code for the given IC address.
166
static inline Code* GetTargetAtAddress(Address address);
167
static inline void SetTargetAtAddress(Address address, Code* target);
168
static void PostPatching(Address address, Code* target, Code* old_target);
171
// Frame pointer for the frame that uses (calls) the IC.
174
// All access to the program counter of an IC structure is indirect
175
// to make the code GC safe. This feature is crucial since
176
// GetProperty and SetProperty are called and they in turn might
177
// invoke the garbage collector.
178
Address* pc_address_;
182
DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
186
// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
187
// cannot make forward declarations to an enum.
190
explicit IC_Utility(IC::UtilityId id)
191
: address_(IC::AddressFromUtilityId(id)), id_(id) {}
193
Address address() const { return address_; }
195
IC::UtilityId id() const { return id_; }
202
class CallICBase: public IC {
204
class Contextual: public BitField<bool, 0, 1> {};
205
class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
207
// Returns a JSFunction or a Failure.
208
MUST_USE_RESULT MaybeObject* LoadFunction(State state,
209
Code::ExtraICState extra_ic_state,
210
Handle<Object> object,
211
Handle<String> name);
214
CallICBase(Code::Kind kind, Isolate* isolate)
215
: IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
217
bool TryUpdateExtraICState(LookupResult* lookup,
218
Handle<Object> object,
219
Code::ExtraICState* extra_ic_state);
221
// Compute a monomorphic stub if possible, otherwise return a null handle.
222
Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
224
Code::ExtraICState extra_state,
225
Handle<Object> object,
226
Handle<String> name);
228
// Update the inline cache and the global stub cache based on the lookup
230
void UpdateCaches(LookupResult* lookup,
232
Code::ExtraICState extra_ic_state,
233
Handle<Object> object,
234
Handle<String> name);
236
// Returns a JSFunction if the object can be called as a function, and
237
// patches the stack to be ready for the call. Otherwise, it returns the
239
Handle<Object> TryCallAsFunction(Handle<Object> object);
241
void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
243
static void Clear(Address address, Code* target);
245
// Platform-specific code generation functions used by both call and
247
static void GenerateMiss(MacroAssembler* masm,
250
Code::ExtraICState extra_state);
252
static void GenerateNormal(MacroAssembler* masm, int argc);
254
static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
257
Code::ExtraICState extra_state);
265
class CallIC: public CallICBase {
267
explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
268
ASSERT(target()->is_call_stub());
271
// Code generator routines.
272
static void GenerateInitialize(MacroAssembler* masm,
274
Code::ExtraICState extra_state) {
275
GenerateMiss(masm, argc, extra_state);
278
static void GenerateMiss(MacroAssembler* masm,
280
Code::ExtraICState extra_state) {
281
CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
284
static void GenerateMegamorphic(MacroAssembler* masm,
286
Code::ExtraICState extra_ic_state);
288
static void GenerateNormal(MacroAssembler* masm, int argc) {
289
CallICBase::GenerateNormal(masm, argc);
290
GenerateMiss(masm, argc, Code::kNoExtraICState);
295
class KeyedCallIC: public CallICBase {
297
explicit KeyedCallIC(Isolate* isolate)
298
: CallICBase(Code::KEYED_CALL_IC, isolate) {
299
ASSERT(target()->is_keyed_call_stub());
302
MUST_USE_RESULT MaybeObject* LoadFunction(State state,
303
Handle<Object> object,
306
// Code generator routines.
307
static void GenerateInitialize(MacroAssembler* masm, int argc) {
308
GenerateMiss(masm, argc);
311
static void GenerateMiss(MacroAssembler* masm, int argc) {
312
CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
313
Code::kNoExtraICState);
316
static void GenerateMegamorphic(MacroAssembler* masm, int argc);
317
static void GenerateNormal(MacroAssembler* masm, int argc);
318
static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
322
class LoadIC: public IC {
324
explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
325
ASSERT(target()->is_load_stub());
328
MUST_USE_RESULT MaybeObject* Load(State state,
329
Handle<Object> object,
330
Handle<String> name);
332
// Code generator routines.
333
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
334
static void GeneratePreMonomorphic(MacroAssembler* masm) {
337
static void GenerateMiss(MacroAssembler* masm);
338
static void GenerateMegamorphic(MacroAssembler* masm);
339
static void GenerateNormal(MacroAssembler* masm);
341
// Specialized code generator routines.
342
static void GenerateArrayLength(MacroAssembler* masm);
343
static void GenerateStringLength(MacroAssembler* masm,
344
bool support_wrappers);
345
static void GenerateFunctionPrototype(MacroAssembler* masm);
348
// Update the inline cache and the global stub cache based on the
350
void UpdateCaches(LookupResult* lookup,
352
Handle<Object> object,
353
Handle<String> name);
356
Handle<Code> megamorphic_stub() {
357
return isolate()->builtins()->LoadIC_Megamorphic();
359
static Code* initialize_stub() {
360
return Isolate::Current()->builtins()->builtin(
361
Builtins::kLoadIC_Initialize);
363
Handle<Code> pre_monomorphic_stub() {
364
return isolate()->builtins()->LoadIC_PreMonomorphic();
367
static void Clear(Address address, Code* target);
373
class KeyedIC: public IC {
378
STORE_TRANSITION_SMI_TO_OBJECT,
379
STORE_TRANSITION_SMI_TO_DOUBLE,
380
STORE_TRANSITION_DOUBLE_TO_OBJECT,
381
STORE_TRANSITION_HOLEY_SMI_TO_OBJECT,
382
STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE,
383
STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
384
STORE_AND_GROW_NO_TRANSITION,
385
STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
386
STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
387
STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT,
388
STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT,
389
STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE,
390
STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT
393
static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
395
STATIC_ASSERT(kGrowICDelta ==
396
STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
397
STORE_TRANSITION_SMI_TO_OBJECT);
398
STATIC_ASSERT(kGrowICDelta ==
399
STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
400
STORE_TRANSITION_SMI_TO_DOUBLE);
401
STATIC_ASSERT(kGrowICDelta ==
402
STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
403
STORE_TRANSITION_DOUBLE_TO_OBJECT);
405
explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
406
virtual ~KeyedIC() {}
408
static inline KeyedAccessGrowMode GetGrowModeFromStubKind(
409
StubKind stub_kind) {
410
return (stub_kind >= STORE_AND_GROW_NO_TRANSITION)
411
? ALLOW_JSARRAY_GROWTH
412
: DO_NOT_ALLOW_JSARRAY_GROWTH;
415
static inline StubKind GetGrowStubKind(StubKind stub_kind) {
416
ASSERT(stub_kind != LOAD);
417
if (stub_kind < STORE_AND_GROW_NO_TRANSITION) {
418
stub_kind = static_cast<StubKind>(static_cast<int>(stub_kind) +
424
virtual Handle<Code> GetElementStubWithoutMapCheck(
426
ElementsKind elements_kind,
427
KeyedAccessGrowMode grow_mode) = 0;
430
virtual Handle<Code> string_stub() {
431
return Handle<Code>::null();
434
virtual Code::Kind kind() const = 0;
436
Handle<Code> ComputeStub(Handle<JSObject> receiver,
438
StrictModeFlag strict_mode,
439
Handle<Code> default_stub);
441
virtual Handle<Code> ComputePolymorphicStub(
442
MapHandleList* receiver_maps,
443
StrictModeFlag strict_mode,
444
KeyedAccessGrowMode grow_mode) = 0;
446
Handle<Code> ComputeMonomorphicStubWithoutMapCheck(
447
Handle<Map> receiver_map,
448
StrictModeFlag strict_mode,
449
KeyedAccessGrowMode grow_mode);
452
void GetReceiverMapsForStub(Handle<Code> stub, MapHandleList* result);
454
Handle<Code> ComputeMonomorphicStub(Handle<Map> receiver_map,
456
StrictModeFlag strict_mode,
457
Handle<Code> default_stub);
459
Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
462
static bool IsTransitionStubKind(StubKind stub_kind) {
463
return stub_kind > STORE_NO_TRANSITION &&
464
stub_kind != STORE_AND_GROW_NO_TRANSITION;
467
static bool IsGrowStubKind(StubKind stub_kind) {
468
return stub_kind >= STORE_AND_GROW_NO_TRANSITION;
471
static StubKind GetNoTransitionStubKind(StubKind stub_kind) {
472
if (!IsTransitionStubKind(stub_kind)) return stub_kind;
473
if (IsGrowStubKind(stub_kind)) return STORE_AND_GROW_NO_TRANSITION;
474
return STORE_NO_TRANSITION;
479
class KeyedLoadIC: public KeyedIC {
481
explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
482
ASSERT(target()->is_keyed_load_stub());
485
MUST_USE_RESULT MaybeObject* Load(State state,
486
Handle<Object> object,
488
bool force_generic_stub);
490
// Code generator routines.
491
static void GenerateMiss(MacroAssembler* masm, bool force_generic);
492
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
493
static void GenerateInitialize(MacroAssembler* masm) {
494
GenerateMiss(masm, false);
496
static void GeneratePreMonomorphic(MacroAssembler* masm) {
497
GenerateMiss(masm, false);
499
static void GenerateGeneric(MacroAssembler* masm);
500
static void GenerateString(MacroAssembler* masm);
501
static void GenerateIndexedInterceptor(MacroAssembler* masm);
502
static void GenerateNonStrictArguments(MacroAssembler* masm);
504
// Bit mask to be tested against bit field for the cases when
505
// generic stub should go into slow case.
506
// Access check is necessary explicitly since generic stub does not perform
508
static const int kSlowCaseBitFieldMask =
509
(1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
511
virtual Handle<Code> GetElementStubWithoutMapCheck(
513
ElementsKind elements_kind,
514
KeyedAccessGrowMode grow_mode);
516
virtual bool IsGeneric() const {
517
return target() == *generic_stub();
521
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
523
virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
524
StrictModeFlag strict_mode,
525
KeyedAccessGrowMode grow_mode);
527
virtual Handle<Code> string_stub() {
528
return isolate()->builtins()->KeyedLoadIC_String();
532
// Update the inline cache.
533
void UpdateCaches(LookupResult* lookup,
535
Handle<Object> object,
536
Handle<String> name);
539
static Code* initialize_stub() {
540
return Isolate::Current()->builtins()->builtin(
541
Builtins::kKeyedLoadIC_Initialize);
543
Handle<Code> megamorphic_stub() {
544
return isolate()->builtins()->KeyedLoadIC_Generic();
546
Handle<Code> generic_stub() const {
547
return isolate()->builtins()->KeyedLoadIC_Generic();
549
Handle<Code> pre_monomorphic_stub() {
550
return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
552
Handle<Code> indexed_interceptor_stub() {
553
return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
555
Handle<Code> non_strict_arguments_stub() {
556
return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
559
static void Clear(Address address, Code* target);
565
class StoreIC: public IC {
567
explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
568
ASSERT(target()->is_store_stub());
571
MUST_USE_RESULT MaybeObject* Store(State state,
572
StrictModeFlag strict_mode,
573
Handle<Object> object,
575
Handle<Object> value);
577
// Code generators for stub routines. Only called once at startup.
578
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
579
static void GenerateMiss(MacroAssembler* masm);
580
static void GenerateMegamorphic(MacroAssembler* masm,
581
StrictModeFlag strict_mode);
582
static void GenerateArrayLength(MacroAssembler* masm);
583
static void GenerateNormal(MacroAssembler* masm);
584
static void GenerateGlobalProxy(MacroAssembler* masm,
585
StrictModeFlag strict_mode);
588
// Update the inline cache and the global stub cache based on the
590
void UpdateCaches(LookupResult* lookup,
592
StrictModeFlag strict_mode,
593
Handle<JSObject> receiver,
595
Handle<Object> value);
597
void set_target(Code* code) {
598
// Strict mode must be preserved across IC patching.
599
ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
600
Code::GetStrictMode(target()->extra_ic_state()));
601
IC::set_target(code);
605
Code* megamorphic_stub() {
606
return isolate()->builtins()->builtin(
607
Builtins::kStoreIC_Megamorphic);
609
Code* megamorphic_stub_strict() {
610
return isolate()->builtins()->builtin(
611
Builtins::kStoreIC_Megamorphic_Strict);
613
static Code* initialize_stub() {
614
return Isolate::Current()->builtins()->builtin(
615
Builtins::kStoreIC_Initialize);
617
static Code* initialize_stub_strict() {
618
return Isolate::Current()->builtins()->builtin(
619
Builtins::kStoreIC_Initialize_Strict);
621
Handle<Code> global_proxy_stub() {
622
return isolate()->builtins()->StoreIC_GlobalProxy();
624
Handle<Code> global_proxy_stub_strict() {
625
return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
628
static void Clear(Address address, Code* target);
634
class KeyedStoreIC: public KeyedIC {
636
explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
637
ASSERT(target()->is_keyed_store_stub());
640
MUST_USE_RESULT MaybeObject* Store(State state,
641
StrictModeFlag strict_mode,
642
Handle<Object> object,
644
Handle<Object> value,
647
// Code generators for stub routines. Only called once at startup.
648
static void GenerateInitialize(MacroAssembler* masm) {
649
GenerateMiss(masm, false);
651
static void GenerateMiss(MacroAssembler* masm, bool force_generic);
652
static void GenerateSlow(MacroAssembler* masm);
653
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
654
StrictModeFlag strict_mode);
655
static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
656
static void GenerateNonStrictArguments(MacroAssembler* masm);
657
static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm);
658
static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm);
660
virtual Handle<Code> GetElementStubWithoutMapCheck(
662
ElementsKind elements_kind,
663
KeyedAccessGrowMode grow_mode);
665
virtual bool IsGeneric() const {
666
return target() == *generic_stub() ||
667
target() == *generic_stub_strict();
671
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
673
virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
674
StrictModeFlag strict_mode,
675
KeyedAccessGrowMode grow_mode);
678
// Update the inline cache.
679
void UpdateCaches(LookupResult* lookup,
681
StrictModeFlag strict_mode,
682
Handle<JSObject> receiver,
684
Handle<Object> value);
686
void set_target(Code* code) {
687
// Strict mode must be preserved across IC patching.
688
ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
689
Code::GetStrictMode(target()->extra_ic_state()));
690
IC::set_target(code);
694
static Code* initialize_stub() {
695
return Isolate::Current()->builtins()->builtin(
696
Builtins::kKeyedStoreIC_Initialize);
698
static Code* initialize_stub_strict() {
699
return Isolate::Current()->builtins()->builtin(
700
Builtins::kKeyedStoreIC_Initialize_Strict);
702
Handle<Code> megamorphic_stub() {
703
return isolate()->builtins()->KeyedStoreIC_Generic();
705
Handle<Code> megamorphic_stub_strict() {
706
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
708
Handle<Code> generic_stub() const {
709
return isolate()->builtins()->KeyedStoreIC_Generic();
711
Handle<Code> generic_stub_strict() const {
712
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
714
Handle<Code> non_strict_arguments_stub() {
715
return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
718
static void Clear(Address address, Code* target);
720
StubKind GetStubKind(Handle<JSObject> receiver,
722
Handle<Object> value);
728
class UnaryOpIC: public IC {
730
// sorted: increasingly more unspecific (ignoring UNINITIALIZED)
731
// TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
739
explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
741
void patch(Code* code);
743
static const char* GetName(TypeInfo type_info);
745
static State ToState(TypeInfo type_info);
747
static TypeInfo GetTypeInfo(Handle<Object> operand);
749
static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
753
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
754
class BinaryOpIC: public IC {
762
BOTH_STRING, // Only used for addition operation.
763
STRING, // Only used for addition operation. At least one string operand.
767
explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
769
void patch(Code* code);
771
static const char* GetName(TypeInfo type_info);
773
static State ToState(TypeInfo type_info);
775
static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
777
static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
781
class CompareIC: public IC {
794
CompareIC(Isolate* isolate, Token::Value op)
795
: IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
797
// Update the inline cache for the given operands.
798
void UpdateCaches(Handle<Object> x, Handle<Object> y);
800
// Factory method for getting an uninitialized compare stub.
801
static Handle<Code> GetUninitialized(Token::Value op);
803
// Helper function for computing the condition for a compare operation.
804
static Condition ComputeCondition(Token::Value op);
806
// Helper function for determining the state of a compare IC.
807
static State ComputeState(Code* target);
809
// Helper function for determining the operation a compare IC is for.
810
static Token::Value ComputeOperation(Code* target);
812
static const char* GetStateName(State state);
815
State TargetState(State state, bool has_inlined_smi_code,
816
Handle<Object> x, Handle<Object> y);
818
bool strict() const { return op_ == Token::EQ_STRICT; }
819
Condition GetCondition() const { return ComputeCondition(op_); }
820
State GetState() { return ComputeState(target()); }
822
static Code* GetRawUninitialized(Token::Value op);
824
static void Clear(Address address, Code* target);
832
class ToBooleanIC: public IC {
834
explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
836
void patch(Code* code);
840
// Helper for BinaryOpIC and CompareIC.
841
enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
842
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
844
} } // namespace v8::internal