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 bool IsQmlGlobal(Handle<Object> receiver) {
114 JSObject* qml_global = isolate_->context()->qml_global();
115 return !qml_global->IsUndefined() && qml_global == *receiver;
118 // Returns if this IC is for contextual (no explicit receiver)
119 // access to properties.
120 bool IsContextual(Handle<Object> receiver) {
121 if (receiver->IsGlobalObject() ||
122 IsQmlGlobal(receiver)) {
123 return SlowIsContextual();
125 ASSERT(!SlowIsContextual());
130 bool SlowIsContextual() {
131 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
134 // Determines which map must be used for keeping the code stub.
135 // These methods should not be called with undefined or null.
136 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
138 static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
140 static inline JSObject* GetCodeCacheHolder(Object* object,
141 InlineCacheHolderFlag holder);
144 Address fp() const { return fp_; }
145 Address pc() const { return *pc_address_; }
146 Isolate* isolate() const { return isolate_; }
148 #ifdef ENABLE_DEBUGGER_SUPPORT
149 // Computes the address in the original code when the code running is
150 // containing break points (calls to DebugBreakXXX builtins).
151 Address OriginalCodeAddress() const;
154 // Set the call-site target.
155 void set_target(Code* code) { SetTargetAtAddress(address(), code); }
158 char TransitionMarkFromState(IC::State state);
160 void TraceIC(const char* type,
166 Failure* TypeError(const char* type,
167 Handle<Object> object,
169 Failure* ReferenceError(const char* type, Handle<String> name);
171 // Access the target code for the given IC address.
172 static inline Code* GetTargetAtAddress(Address address);
173 static inline void SetTargetAtAddress(Address address, Code* target);
174 static void PostPatching(Address address, Code* target, Code* old_target);
177 // Frame pointer for the frame that uses (calls) the IC.
180 // All access to the program counter of an IC structure is indirect
181 // to make the code GC safe. This feature is crucial since
182 // GetProperty and SetProperty are called and they in turn might
183 // invoke the garbage collector.
184 Address* pc_address_;
188 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
192 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
193 // cannot make forward declarations to an enum.
196 explicit IC_Utility(IC::UtilityId id)
197 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
199 Address address() const { return address_; }
201 IC::UtilityId id() const { return id_; }
208 class CallICBase: public IC {
210 class Contextual: public BitField<bool, 0, 1> {};
211 class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
213 // Returns a JSFunction or a Failure.
214 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
215 Code::ExtraICState extra_ic_state,
216 Handle<Object> object,
217 Handle<String> name);
220 CallICBase(Code::Kind kind, Isolate* isolate)
221 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
223 bool TryUpdateExtraICState(LookupResult* lookup,
224 Handle<Object> object,
225 Code::ExtraICState* extra_ic_state);
227 // Compute a monomorphic stub if possible, otherwise return a null handle.
228 Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
230 Code::ExtraICState extra_state,
231 Handle<Object> object,
232 Handle<String> name);
234 // Update the inline cache and the global stub cache based on the lookup
236 void UpdateCaches(LookupResult* lookup,
238 Code::ExtraICState extra_ic_state,
239 Handle<Object> object,
240 Handle<String> name);
242 // Returns a JSFunction if the object can be called as a function, and
243 // patches the stack to be ready for the call. Otherwise, it returns the
245 Handle<Object> TryCallAsFunction(Handle<Object> object);
247 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
249 static void Clear(Address address, Code* target);
251 // Platform-specific code generation functions used by both call and
253 static void GenerateMiss(MacroAssembler* masm,
256 Code::ExtraICState extra_state);
258 static void GenerateNormal(MacroAssembler* masm, int argc);
260 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
263 Code::ExtraICState extra_state);
271 class CallIC: public CallICBase {
273 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
274 ASSERT(target()->is_call_stub());
277 // Code generator routines.
278 static void GenerateInitialize(MacroAssembler* masm,
280 Code::ExtraICState extra_state) {
281 GenerateMiss(masm, argc, extra_state);
284 static void GenerateMiss(MacroAssembler* masm,
286 Code::ExtraICState extra_state) {
287 CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
290 static void GenerateMegamorphic(MacroAssembler* masm,
292 Code::ExtraICState extra_ic_state);
294 static void GenerateNormal(MacroAssembler* masm, int argc) {
295 CallICBase::GenerateNormal(masm, argc);
296 GenerateMiss(masm, argc, Code::kNoExtraICState);
301 class KeyedCallIC: public CallICBase {
303 explicit KeyedCallIC(Isolate* isolate)
304 : CallICBase(Code::KEYED_CALL_IC, isolate) {
305 ASSERT(target()->is_keyed_call_stub());
308 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
309 Handle<Object> object,
312 // Code generator routines.
313 static void GenerateInitialize(MacroAssembler* masm, int argc) {
314 GenerateMiss(masm, argc);
317 static void GenerateMiss(MacroAssembler* masm, int argc) {
318 CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
319 Code::kNoExtraICState);
322 static void GenerateMegamorphic(MacroAssembler* masm, int argc);
323 static void GenerateNormal(MacroAssembler* masm, int argc);
324 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
328 class LoadIC: public IC {
330 explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
331 ASSERT(target()->is_load_stub());
334 MUST_USE_RESULT MaybeObject* Load(State state,
335 Handle<Object> object,
336 Handle<String> name);
338 // Code generator routines.
339 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
340 static void GeneratePreMonomorphic(MacroAssembler* masm) {
343 static void GenerateMiss(MacroAssembler* masm);
344 static void GenerateMegamorphic(MacroAssembler* masm);
345 static void GenerateNormal(MacroAssembler* masm);
347 // Specialized code generator routines.
348 static void GenerateArrayLength(MacroAssembler* masm);
349 static void GenerateStringLength(MacroAssembler* masm,
350 bool support_wrappers);
351 static void GenerateFunctionPrototype(MacroAssembler* masm);
354 // Update the inline cache and the global stub cache based on the
356 void UpdateCaches(LookupResult* lookup,
358 Handle<Object> object,
359 Handle<String> name);
362 Handle<Code> megamorphic_stub() {
363 return isolate()->builtins()->LoadIC_Megamorphic();
365 static Code* initialize_stub() {
366 return Isolate::Current()->builtins()->builtin(
367 Builtins::kLoadIC_Initialize);
369 Handle<Code> pre_monomorphic_stub() {
370 return isolate()->builtins()->LoadIC_PreMonomorphic();
373 static void Clear(Address address, Code* target);
379 class KeyedIC: public IC {
384 STORE_TRANSITION_SMI_TO_OBJECT,
385 STORE_TRANSITION_SMI_TO_DOUBLE,
386 STORE_TRANSITION_DOUBLE_TO_OBJECT,
387 STORE_AND_GROW_NO_TRANSITION,
388 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
389 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
390 STORE_AND_GROW_TRANSITION_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<JSObject> receiver,
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;
473 class KeyedLoadIC: public KeyedIC {
475 explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
476 ASSERT(target()->is_keyed_load_stub());
479 MUST_USE_RESULT MaybeObject* Load(State state,
480 Handle<Object> object,
482 bool force_generic_stub);
484 // Code generator routines.
485 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
486 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
487 static void GenerateInitialize(MacroAssembler* masm) {
488 GenerateMiss(masm, false);
490 static void GeneratePreMonomorphic(MacroAssembler* masm) {
491 GenerateMiss(masm, false);
493 static void GenerateGeneric(MacroAssembler* masm);
494 static void GenerateString(MacroAssembler* masm);
495 static void GenerateIndexedInterceptor(MacroAssembler* masm);
496 static void GenerateNonStrictArguments(MacroAssembler* masm);
498 // Bit mask to be tested against bit field for the cases when
499 // generic stub should go into slow case.
500 // Access check is necessary explicitly since generic stub does not perform
502 static const int kSlowCaseBitFieldMask =
503 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
505 virtual Handle<Code> GetElementStubWithoutMapCheck(
507 ElementsKind elements_kind,
508 KeyedAccessGrowMode grow_mode);
510 virtual bool IsGeneric() const {
511 return target() == *generic_stub();
515 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
517 virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
518 StrictModeFlag strict_mode,
519 KeyedAccessGrowMode grow_mode);
521 virtual Handle<Code> string_stub() {
522 return isolate()->builtins()->KeyedLoadIC_String();
526 // Update the inline cache.
527 void UpdateCaches(LookupResult* lookup,
529 Handle<Object> object,
530 Handle<String> name);
533 static Code* initialize_stub() {
534 return Isolate::Current()->builtins()->builtin(
535 Builtins::kKeyedLoadIC_Initialize);
537 Handle<Code> megamorphic_stub() {
538 return isolate()->builtins()->KeyedLoadIC_Generic();
540 Handle<Code> generic_stub() const {
541 return isolate()->builtins()->KeyedLoadIC_Generic();
543 Handle<Code> pre_monomorphic_stub() {
544 return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
546 Handle<Code> indexed_interceptor_stub() {
547 return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
549 Handle<Code> non_strict_arguments_stub() {
550 return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
553 static void Clear(Address address, Code* target);
559 class StoreIC: public IC {
561 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
562 ASSERT(target()->is_store_stub());
565 MUST_USE_RESULT MaybeObject* Store(State state,
566 StrictModeFlag strict_mode,
567 Handle<Object> object,
569 Handle<Object> value);
571 // Code generators for stub routines. Only called once at startup.
572 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
573 static void GenerateMiss(MacroAssembler* masm);
574 static void GenerateMegamorphic(MacroAssembler* masm,
575 StrictModeFlag strict_mode);
576 static void GenerateArrayLength(MacroAssembler* masm);
577 static void GenerateNormal(MacroAssembler* masm);
578 static void GenerateGlobalProxy(MacroAssembler* masm,
579 StrictModeFlag strict_mode);
582 // Update the inline cache and the global stub cache based on the
584 void UpdateCaches(LookupResult* lookup,
586 StrictModeFlag strict_mode,
587 Handle<JSObject> receiver,
589 Handle<Object> value);
591 void set_target(Code* code) {
592 // Strict mode must be preserved across IC patching.
593 ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
594 Code::GetStrictMode(target()->extra_ic_state()));
595 IC::set_target(code);
599 Code* megamorphic_stub() {
600 return isolate()->builtins()->builtin(
601 Builtins::kStoreIC_Megamorphic);
603 Code* megamorphic_stub_strict() {
604 return isolate()->builtins()->builtin(
605 Builtins::kStoreIC_Megamorphic_Strict);
607 static Code* initialize_stub() {
608 return Isolate::Current()->builtins()->builtin(
609 Builtins::kStoreIC_Initialize);
611 static Code* initialize_stub_strict() {
612 return Isolate::Current()->builtins()->builtin(
613 Builtins::kStoreIC_Initialize_Strict);
615 Handle<Code> global_proxy_stub() {
616 return isolate()->builtins()->StoreIC_GlobalProxy();
618 Handle<Code> global_proxy_stub_strict() {
619 return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
622 static void Clear(Address address, Code* target);
628 class KeyedStoreIC: public KeyedIC {
630 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
631 ASSERT(target()->is_keyed_store_stub());
634 MUST_USE_RESULT MaybeObject* Store(State state,
635 StrictModeFlag strict_mode,
636 Handle<Object> object,
638 Handle<Object> value,
641 // Code generators for stub routines. Only called once at startup.
642 static void GenerateInitialize(MacroAssembler* masm) {
643 GenerateMiss(masm, false);
645 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
646 static void GenerateSlow(MacroAssembler* masm);
647 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
648 StrictModeFlag strict_mode);
649 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
650 static void GenerateNonStrictArguments(MacroAssembler* masm);
651 static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm);
652 static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm);
654 virtual Handle<Code> GetElementStubWithoutMapCheck(
656 ElementsKind elements_kind,
657 KeyedAccessGrowMode grow_mode);
659 virtual bool IsGeneric() const {
660 return target() == *generic_stub() ||
661 target() == *generic_stub_strict();
665 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
667 virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
668 StrictModeFlag strict_mode,
669 KeyedAccessGrowMode grow_mode);
672 // Update the inline cache.
673 void UpdateCaches(LookupResult* lookup,
675 StrictModeFlag strict_mode,
676 Handle<JSObject> receiver,
678 Handle<Object> value);
680 void set_target(Code* code) {
681 // Strict mode must be preserved across IC patching.
682 ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
683 Code::GetStrictMode(target()->extra_ic_state()));
684 IC::set_target(code);
688 static Code* initialize_stub() {
689 return Isolate::Current()->builtins()->builtin(
690 Builtins::kKeyedStoreIC_Initialize);
692 static Code* initialize_stub_strict() {
693 return Isolate::Current()->builtins()->builtin(
694 Builtins::kKeyedStoreIC_Initialize_Strict);
696 Handle<Code> megamorphic_stub() {
697 return isolate()->builtins()->KeyedStoreIC_Generic();
699 Handle<Code> megamorphic_stub_strict() {
700 return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
702 Handle<Code> generic_stub() const {
703 return isolate()->builtins()->KeyedStoreIC_Generic();
705 Handle<Code> generic_stub_strict() const {
706 return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
708 Handle<Code> non_strict_arguments_stub() {
709 return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
712 static void Clear(Address address, Code* target);
714 StubKind GetStubKind(Handle<JSObject> receiver,
716 Handle<Object> value);
722 class UnaryOpIC: public IC {
724 // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
725 // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
733 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
735 void patch(Code* code);
737 static const char* GetName(TypeInfo type_info);
739 static State ToState(TypeInfo type_info);
741 static TypeInfo GetTypeInfo(Handle<Object> operand);
743 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
747 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
748 class BinaryOpIC: public IC {
756 BOTH_STRING, // Only used for addition operation.
757 STRING, // Only used for addition operation. At least one string operand.
761 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
763 void patch(Code* code);
765 static const char* GetName(TypeInfo type_info);
767 static State ToState(TypeInfo type_info);
769 static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
771 static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
775 class CompareIC: public IC {
788 CompareIC(Isolate* isolate, Token::Value op)
789 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
791 // Update the inline cache for the given operands.
792 void UpdateCaches(Handle<Object> x, Handle<Object> y);
794 // Factory method for getting an uninitialized compare stub.
795 static Handle<Code> GetUninitialized(Token::Value op);
797 // Helper function for computing the condition for a compare operation.
798 static Condition ComputeCondition(Token::Value op);
800 // Helper function for determining the state of a compare IC.
801 static State ComputeState(Code* target);
803 // Helper function for determining the operation a compare IC is for.
804 static Token::Value ComputeOperation(Code* target);
806 static const char* GetStateName(State state);
809 State TargetState(State state, bool has_inlined_smi_code,
810 Handle<Object> x, Handle<Object> y);
812 bool strict() const { return op_ == Token::EQ_STRICT; }
813 Condition GetCondition() const { return ComputeCondition(op_); }
814 State GetState() { return ComputeState(target()); }
816 static Code* GetRawUninitialized(Token::Value op);
818 static void Clear(Address address, Code* target);
826 class ToBooleanIC: public IC {
828 explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
830 void patch(Code* code);
834 // Helper for BinaryOpIC and CompareIC.
835 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
836 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
838 } } // namespace v8::internal