The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / ic.h @ f230a1cf

History | View | Annotate | Download (29.9 KB)

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
4
// met:
5
//
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.
15
//
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.
27

    
28
#ifndef V8_IC_H_
29
#define V8_IC_H_
30

    
31
#include "macro-assembler.h"
32
#include "type-info.h"
33

    
34
namespace v8 {
35
namespace internal {
36

    
37

    
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)                             \
41
  ICU(LoadIC_Miss)                                    \
42
  ICU(KeyedLoadIC_Miss)                               \
43
  ICU(KeyedLoadIC_MissForceGeneric)                   \
44
  ICU(CallIC_Miss)                                    \
45
  ICU(KeyedCallIC_Miss)                               \
46
  ICU(StoreIC_Miss)                                   \
47
  ICU(StoreIC_ArrayLength)                            \
48
  ICU(StoreIC_Slow)                                   \
49
  ICU(SharedStoreIC_ExtendStorage)                    \
50
  ICU(KeyedStoreIC_Miss)                              \
51
  ICU(KeyedStoreIC_MissForceGeneric)                  \
52
  ICU(KeyedStoreIC_Slow)                              \
53
  /* Utilities for IC stubs. */                       \
54
  ICU(StoreCallbackProperty)                          \
55
  ICU(LoadPropertyWithInterceptorOnly)                \
56
  ICU(LoadPropertyWithInterceptorForLoad)             \
57
  ICU(LoadPropertyWithInterceptorForCall)             \
58
  ICU(KeyedLoadPropertyWithInterceptor)               \
59
  ICU(StoreInterceptorProperty)                       \
60
  ICU(CompareIC_Miss)                                 \
61
  ICU(BinaryOpIC_Miss)                                \
62
  ICU(CompareNilIC_Miss)                              \
63
  ICU(Unreachable)                                    \
64
  ICU(ToBooleanIC_Miss)
65
//
66
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
67
// and KeyedStoreIC.
68
//
69
class IC {
70
 public:
71
  // The ids for utility called from the generated code.
72
  enum UtilityId {
73
  #define CONST_NAME(name) k##name,
74
    IC_UTIL_LIST(CONST_NAME)
75
  #undef CONST_NAME
76
    kUtilityCount
77
  };
78

    
79
  // Looks up the address of the named utility.
80
  static Address AddressFromUtilityId(UtilityId id);
81

    
82
  // Alias the inline cache state type to make the IC code more readable.
83
  typedef InlineCacheState State;
84

    
85
  // The IC code is either invoked with no extra frames on the stack
86
  // or with a single extra frame for supporting calls.
87
  enum FrameDepth {
88
    NO_EXTRA_FRAME = 0,
89
    EXTRA_CALL_FRAME = 1
90
  };
91

    
92
  // Construct the IC structure with the given number of extra
93
  // JavaScript frames on the stack.
94
  IC(FrameDepth depth, Isolate* isolate);
95
  virtual ~IC() {}
96

    
97
  // Get the call-site target; used for determining the state.
98
  Handle<Code> target() const { return target_; }
99
  Code* raw_target() const { return GetTargetAtAddress(address()); }
100

    
101
  State state() const { return state_; }
102
  inline Address address() const;
103

    
104
  // Compute the current IC state based on the target stub, receiver and name.
105
  void UpdateState(Handle<Object> receiver, Handle<Object> name);
106
  void MarkMonomorphicPrototypeFailure() {
107
    state_ = MONOMORPHIC_PROTOTYPE_FAILURE;
108
  }
109

    
110
  // Clear the inline cache to initial state.
111
  static void Clear(Isolate* isolate, Address address);
112

    
113
  // Computes the reloc info for this IC. This is a fairly expensive
114
  // operation as it has to search through the heap to find the code
115
  // object that contains this IC site.
116
  RelocInfo::Mode ComputeMode();
117

    
118
  // Returns if this IC is for contextual (no explicit receiver)
119
  // access to properties.
120
  bool IsUndeclaredGlobal(Handle<Object> receiver) {
121
    if (receiver->IsGlobalObject()) {
122
      return SlowIsUndeclaredGlobal();
123
    } else {
124
      ASSERT(!SlowIsUndeclaredGlobal());
125
      return false;
126
    }
127
  }
128

    
129
  bool SlowIsUndeclaredGlobal() {
130
    return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
131
  }
132

    
133
  // Determines which map must be used for keeping the code stub.
134
  // These methods should not be called with undefined or null.
135
  static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
136
                                                            JSObject* holder);
137
  static inline JSObject* GetCodeCacheHolder(Isolate* isolate,
138
                                             Object* object,
139
                                             InlineCacheHolderFlag holder);
140

    
141
  static bool IsCleared(Code* code) {
142
    InlineCacheState state = code->ic_state();
143
    return state == UNINITIALIZED || state == PREMONOMORPHIC;
144
  }
145

    
146
 protected:
147
  Address fp() const { return fp_; }
148
  Address pc() const { return *pc_address_; }
149
  Isolate* isolate() const { return isolate_; }
150

    
151
#ifdef ENABLE_DEBUGGER_SUPPORT
152
  // Computes the address in the original code when the code running is
153
  // containing break points (calls to DebugBreakXXX builtins).
154
  Address OriginalCodeAddress() const;
155
#endif
156

    
157
  // Set the call-site target.
158
  void set_target(Code* code) {
159
    SetTargetAtAddress(address(), code);
160
    target_set_ = true;
161
  }
162

    
163
  bool is_target_set() { return target_set_; }
164

    
165
#ifdef DEBUG
166
  char TransitionMarkFromState(IC::State state);
167

    
168
  void TraceIC(const char* type, Handle<Object> name);
169
#endif
170

    
171
  Failure* TypeError(const char* type,
172
                     Handle<Object> object,
173
                     Handle<Object> key);
174
  Failure* ReferenceError(const char* type, Handle<String> name);
175

    
176
  // Access the target code for the given IC address.
177
  static inline Code* GetTargetAtAddress(Address address);
178
  static inline void SetTargetAtAddress(Address address, Code* target);
179
  static void PostPatching(Address address, Code* target, Code* old_target);
180

    
181
  // Compute the handler either by compiling or by retrieving a cached version.
182
  Handle<Code> ComputeHandler(LookupResult* lookup,
183
                              Handle<JSObject> receiver,
184
                              Handle<String> name,
185
                              Handle<Object> value = Handle<Code>::null());
186
  virtual Handle<Code> CompileHandler(LookupResult* lookup,
187
                                      Handle<JSObject> receiver,
188
                                      Handle<String> name,
189
                                      Handle<Object> value) {
190
    UNREACHABLE();
191
    return Handle<Code>::null();
192
  }
193
  void UpdateMonomorphicIC(Handle<HeapObject> receiver,
194
                           Handle<Code> handler,
195
                           Handle<String> name);
196

    
197
  bool UpdatePolymorphicIC(Handle<HeapObject> receiver,
198
                           Handle<String> name,
199
                           Handle<Code> code);
200

    
201
  void CopyICToMegamorphicCache(Handle<String> name);
202
  bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
203
  void PatchCache(Handle<HeapObject> receiver,
204
                  Handle<String> name,
205
                  Handle<Code> code);
206
  virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
207
  virtual Code::Kind kind() const {
208
    UNREACHABLE();
209
    return Code::STUB;
210
  }
211
  virtual Handle<Code> slow_stub() const {
212
    UNREACHABLE();
213
    return Handle<Code>::null();
214
  }
215
  virtual Handle<Code> megamorphic_stub() {
216
    UNREACHABLE();
217
    return Handle<Code>::null();
218
  }
219
  virtual Handle<Code> generic_stub() const {
220
    UNREACHABLE();
221
    return Handle<Code>::null();
222
  }
223
  virtual StrictModeFlag strict_mode() const { return kNonStrictMode; }
224
  bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
225
                                              Handle<String> name);
226
  void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name);
227

    
228
 private:
229
  // Frame pointer for the frame that uses (calls) the IC.
230
  Address fp_;
231

    
232
  // All access to the program counter of an IC structure is indirect
233
  // to make the code GC safe. This feature is crucial since
234
  // GetProperty and SetProperty are called and they in turn might
235
  // invoke the garbage collector.
236
  Address* pc_address_;
237

    
238
  Isolate* isolate_;
239

    
240
  // The original code target that missed.
241
  Handle<Code> target_;
242
  State state_;
243
  bool target_set_;
244

    
245
  DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
246
};
247

    
248

    
249
// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
250
// cannot make forward declarations to an enum.
251
class IC_Utility {
252
 public:
253
  explicit IC_Utility(IC::UtilityId id)
254
    : address_(IC::AddressFromUtilityId(id)), id_(id) {}
255

    
256
  Address address() const { return address_; }
257

    
258
  IC::UtilityId id() const { return id_; }
259
 private:
260
  Address address_;
261
  IC::UtilityId id_;
262
};
263

    
264

    
265
class CallICBase: public IC {
266
 public:
267
  class Contextual: public BitField<bool, 0, 1> {};
268
  class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
269

    
270
  // Returns a JSFunction or a Failure.
271
  MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
272
                                            Handle<String> name);
273

    
274
 protected:
275
  CallICBase(Code::Kind kind, Isolate* isolate)
276
      : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
277

    
278
  virtual Code::ExtraICState extra_ic_state() { return Code::kNoExtraICState; }
279

    
280
  // Compute a monomorphic stub if possible, otherwise return a null handle.
281
  Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
282
                                      Handle<Object> object,
283
                                      Handle<String> name);
284

    
285
  // Update the inline cache and the global stub cache based on the lookup
286
  // result.
287
  void UpdateCaches(LookupResult* lookup,
288
                    Handle<Object> object,
289
                    Handle<String> name);
290

    
291
  // Returns a JSFunction if the object can be called as a function, and
292
  // patches the stack to be ready for the call.  Otherwise, it returns the
293
  // undefined value.
294
  Handle<Object> TryCallAsFunction(Handle<Object> object);
295

    
296
  void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
297

    
298
  static void Clear(Address address, Code* target);
299

    
300
  // Platform-specific code generation functions used by both call and
301
  // keyed call.
302
  static void GenerateMiss(MacroAssembler* masm,
303
                           int argc,
304
                           IC::UtilityId id,
305
                           Code::ExtraICState extra_state);
306

    
307
  static void GenerateNormal(MacroAssembler* masm, int argc);
308

    
309
  static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
310
                                            int argc,
311
                                            Code::Kind kind,
312
                                            Code::ExtraICState extra_state);
313

    
314
  virtual Handle<Code> megamorphic_stub();
315
  virtual Handle<Code> pre_monomorphic_stub();
316

    
317
  Code::Kind kind_;
318

    
319
  friend class IC;
320
};
321

    
322

    
323
class CallIC: public CallICBase {
324
 public:
325
  explicit CallIC(Isolate* isolate)
326
      : CallICBase(Code::CALL_IC, isolate),
327
        extra_ic_state_(target()->extra_ic_state()) {
328
    ASSERT(target()->is_call_stub());
329
  }
330

    
331
  // Code generator routines.
332
  static void GenerateInitialize(MacroAssembler* masm,
333
                                 int argc,
334
                                 Code::ExtraICState extra_state) {
335
    GenerateMiss(masm, argc, extra_state);
336
  }
337

    
338
  static void GenerateMiss(MacroAssembler* masm,
339
                           int argc,
340
                           Code::ExtraICState extra_state) {
341
    CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
342
  }
343

    
344
  static void GenerateMegamorphic(MacroAssembler* masm,
345
                                  int argc,
346
                                  Code::ExtraICState extra_ic_state);
347

    
348
  static void GenerateNormal(MacroAssembler* masm, int argc) {
349
    CallICBase::GenerateNormal(masm, argc);
350
    GenerateMiss(masm, argc, Code::kNoExtraICState);
351
  }
352
  bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object);
353

    
354
 protected:
355
  virtual Code::ExtraICState extra_ic_state() { return extra_ic_state_; }
356

    
357
 private:
358
  Code::ExtraICState extra_ic_state_;
359
};
360

    
361

    
362
class KeyedCallIC: public CallICBase {
363
 public:
364
  explicit KeyedCallIC(Isolate* isolate)
365
      : CallICBase(Code::KEYED_CALL_IC, isolate) {
366
    ASSERT(target()->is_keyed_call_stub());
367
  }
368

    
369
  MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
370
                                            Handle<Object> key);
371

    
372
  // Code generator routines.
373
  static void GenerateInitialize(MacroAssembler* masm, int argc) {
374
    GenerateMiss(masm, argc);
375
  }
376

    
377
  static void GenerateMiss(MacroAssembler* masm, int argc) {
378
    CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
379
                             Code::kNoExtraICState);
380
  }
381

    
382
  static void GenerateMegamorphic(MacroAssembler* masm, int argc);
383
  static void GenerateNormal(MacroAssembler* masm, int argc);
384
  static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
385
};
386

    
387

    
388
class LoadIC: public IC {
389
 public:
390
  explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
391
    ASSERT(target()->is_load_stub() || target()->is_keyed_load_stub());
392
  }
393

    
394
  // Code generator routines.
395
  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
396
  static void GeneratePreMonomorphic(MacroAssembler* masm) {
397
    GenerateMiss(masm);
398
  }
399
  static void GenerateMiss(MacroAssembler* masm);
400
  static void GenerateMegamorphic(MacroAssembler* masm);
401
  static void GenerateNormal(MacroAssembler* masm);
402
  static void GenerateRuntimeGetProperty(MacroAssembler* masm);
403

    
404
  MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
405
                                    Handle<String> name);
406

    
407
 protected:
408
  virtual Code::Kind kind() const { return Code::LOAD_IC; }
409

    
410
  virtual Handle<Code> slow_stub() const {
411
    return isolate()->builtins()->LoadIC_Slow();
412
  }
413

    
414
  virtual Handle<Code> megamorphic_stub() {
415
    return isolate()->builtins()->LoadIC_Megamorphic();
416
  }
417

    
418
  // Update the inline cache and the global stub cache based on the
419
  // lookup result.
420
  void UpdateCaches(LookupResult* lookup,
421
                    Handle<Object> object,
422
                    Handle<String> name);
423

    
424
  virtual Handle<Code> CompileHandler(LookupResult* lookup,
425
                                      Handle<JSObject> receiver,
426
                                      Handle<String> name,
427
                                      Handle<Object> unused);
428

    
429
 private:
430
  // Stub accessors.
431
  static Handle<Code> initialize_stub(Isolate* isolate) {
432
    return isolate->builtins()->LoadIC_Initialize();
433
  }
434

    
435
  static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
436
    return isolate->builtins()->LoadIC_PreMonomorphic();
437
  }
438

    
439
  virtual Handle<Code> pre_monomorphic_stub() {
440
    return pre_monomorphic_stub(isolate());
441
  }
442

    
443
  Handle<Code> SimpleFieldLoad(int offset,
444
                               bool inobject = true,
445
                               Representation representation =
446
                                    Representation::Tagged());
447

    
448
  static void Clear(Isolate* isolate, Address address, Code* target);
449

    
450
  friend class IC;
451
};
452

    
453

    
454
enum ICMissMode {
455
  MISS_FORCE_GENERIC,
456
  MISS
457
};
458

    
459

    
460
class KeyedLoadIC: public LoadIC {
461
 public:
462
  explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate)
463
      : LoadIC(depth, isolate) {
464
    ASSERT(target()->is_keyed_load_stub());
465
  }
466

    
467
  MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
468
                                    Handle<Object> key,
469
                                    ICMissMode force_generic);
470

    
471
  // Code generator routines.
472
  static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
473
  static void GenerateRuntimeGetProperty(MacroAssembler* masm);
474
  static void GenerateInitialize(MacroAssembler* masm) {
475
    GenerateMiss(masm, MISS);
476
  }
477
  static void GeneratePreMonomorphic(MacroAssembler* masm) {
478
    GenerateMiss(masm, MISS);
479
  }
480
  static void GenerateGeneric(MacroAssembler* masm);
481
  static void GenerateString(MacroAssembler* masm);
482
  static void GenerateIndexedInterceptor(MacroAssembler* masm);
483
  static void GenerateNonStrictArguments(MacroAssembler* masm);
484

    
485
  // Bit mask to be tested against bit field for the cases when
486
  // generic stub should go into slow case.
487
  // Access check is necessary explicitly since generic stub does not perform
488
  // map checks.
489
  static const int kSlowCaseBitFieldMask =
490
      (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
491

    
492
 protected:
493
  virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
494

    
495
  Handle<Code> LoadElementStub(Handle<JSObject> receiver);
496

    
497
  virtual Handle<Code> megamorphic_stub() {
498
    return isolate()->builtins()->KeyedLoadIC_Generic();
499
  }
500
  virtual Handle<Code> generic_stub() const {
501
    return isolate()->builtins()->KeyedLoadIC_Generic();
502
  }
503
  virtual Handle<Code> slow_stub() const {
504
    return isolate()->builtins()->KeyedLoadIC_Slow();
505
  }
506

    
507
  virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
508

    
509
 private:
510
  // Stub accessors.
511
  static Handle<Code> initialize_stub(Isolate* isolate) {
512
    return isolate->builtins()->KeyedLoadIC_Initialize();
513
  }
514
  static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
515
    return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
516
  }
517
  virtual Handle<Code> pre_monomorphic_stub() {
518
    return pre_monomorphic_stub(isolate());
519
  }
520
  Handle<Code> indexed_interceptor_stub() {
521
    return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
522
  }
523
  Handle<Code> non_strict_arguments_stub() {
524
    return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
525
  }
526
  Handle<Code> string_stub() {
527
    return isolate()->builtins()->KeyedLoadIC_String();
528
  }
529

    
530
  static void Clear(Isolate* isolate, Address address, Code* target);
531

    
532
  friend class IC;
533
};
534

    
535

    
536
class StoreIC: public IC {
537
 public:
538
  StoreIC(FrameDepth depth, Isolate* isolate)
539
      : IC(depth, isolate),
540
        strict_mode_(Code::GetStrictMode(target()->extra_ic_state())) {
541
    ASSERT(target()->is_store_stub() || target()->is_keyed_store_stub());
542
  }
543

    
544
  virtual StrictModeFlag strict_mode() const { return strict_mode_; }
545

    
546
  // Code generators for stub routines. Only called once at startup.
547
  static void GenerateSlow(MacroAssembler* masm);
548
  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
549
  static void GeneratePreMonomorphic(MacroAssembler* masm) {
550
    GenerateMiss(masm);
551
  }
552
  static void GenerateMiss(MacroAssembler* masm);
553
  static void GenerateMegamorphic(MacroAssembler* masm,
554
                                  StrictModeFlag strict_mode);
555
  static void GenerateNormal(MacroAssembler* masm);
556
  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
557
                                         StrictModeFlag strict_mode);
558

    
559
  MUST_USE_RESULT MaybeObject* Store(
560
      Handle<Object> object,
561
      Handle<String> name,
562
      Handle<Object> value,
563
      JSReceiver::StoreFromKeyed store_mode =
564
          JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
565

    
566
 protected:
567
  virtual Code::Kind kind() const { return Code::STORE_IC; }
568
  virtual Handle<Code> megamorphic_stub() {
569
    if (strict_mode() == kStrictMode) {
570
      return isolate()->builtins()->StoreIC_Megamorphic_Strict();
571
    } else {
572
      return isolate()->builtins()->StoreIC_Megamorphic();
573
    }
574
  }
575
  // Stub accessors.
576
  virtual Handle<Code> generic_stub() const {
577
    if (strict_mode() == kStrictMode) {
578
      return isolate()->builtins()->StoreIC_Generic_Strict();
579
    } else {
580
      return isolate()->builtins()->StoreIC_Generic();
581
    }
582
  }
583

    
584
  virtual Handle<Code> slow_stub() const {
585
    if (strict_mode() == kStrictMode) {
586
      return isolate()->builtins()->StoreIC_Slow_Strict();
587
    } else {
588
      return isolate()->builtins()->StoreIC_Slow();
589
    }
590
  }
591

    
592
  virtual Handle<Code> pre_monomorphic_stub() {
593
    return pre_monomorphic_stub(isolate(), strict_mode());
594
  }
595

    
596
  static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
597
                                           StrictModeFlag strict_mode) {
598
    if (strict_mode == kStrictMode) {
599
      return isolate->builtins()->StoreIC_PreMonomorphic_Strict();
600
    } else {
601
      return isolate->builtins()->StoreIC_PreMonomorphic();
602
    }
603
  }
604

    
605
  virtual Handle<Code> global_proxy_stub() {
606
    if (strict_mode() == kStrictMode) {
607
      return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
608
    } else {
609
      return isolate()->builtins()->StoreIC_GlobalProxy();
610
    }
611
  }
612

    
613
  // Update the inline cache and the global stub cache based on the
614
  // lookup result.
615
  void UpdateCaches(LookupResult* lookup,
616
                    Handle<JSObject> receiver,
617
                    Handle<String> name,
618
                    Handle<Object> value);
619
  virtual Handle<Code> CompileHandler(LookupResult* lookup,
620
                                      Handle<JSObject> receiver,
621
                                      Handle<String> name,
622
                                      Handle<Object> value);
623

    
624
 private:
625
  void set_target(Code* code) {
626
    // Strict mode must be preserved across IC patching.
627
    ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
628
           Code::GetStrictMode(target()->extra_ic_state()));
629
    IC::set_target(code);
630
  }
631

    
632
  static Handle<Code> initialize_stub(Isolate* isolate,
633
                                      StrictModeFlag strict_mode) {
634
    if (strict_mode == kStrictMode) {
635
      return isolate->builtins()->StoreIC_Initialize_Strict();
636
    } else {
637
      return isolate->builtins()->StoreIC_Initialize();
638
    }
639
  }
640

    
641
  static void Clear(Isolate* isolate, Address address, Code* target);
642

    
643
  StrictModeFlag strict_mode_;
644

    
645
  friend class IC;
646
};
647

    
648

    
649
enum KeyedStoreCheckMap {
650
  kDontCheckMap,
651
  kCheckMap
652
};
653

    
654

    
655
enum KeyedStoreIncrementLength {
656
  kDontIncrementLength,
657
  kIncrementLength
658
};
659

    
660

    
661
class KeyedStoreIC: public StoreIC {
662
 public:
663
  KeyedStoreIC(FrameDepth depth, Isolate* isolate)
664
      : StoreIC(depth, isolate) {
665
    ASSERT(target()->is_keyed_store_stub());
666
  }
667

    
668
  MUST_USE_RESULT MaybeObject* Store(Handle<Object> object,
669
                                     Handle<Object> name,
670
                                     Handle<Object> value,
671
                                     ICMissMode force_generic);
672

    
673
  // Code generators for stub routines.  Only called once at startup.
674
  static void GenerateInitialize(MacroAssembler* masm) {
675
    GenerateMiss(masm, MISS);
676
  }
677
  static void GeneratePreMonomorphic(MacroAssembler* masm) {
678
    GenerateMiss(masm, MISS);
679
  }
680
  static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
681
  static void GenerateSlow(MacroAssembler* masm);
682
  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
683
                                         StrictModeFlag strict_mode);
684
  static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
685
  static void GenerateNonStrictArguments(MacroAssembler* masm);
686

    
687
 protected:
688
  virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
689

    
690
  virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
691

    
692
  virtual Handle<Code> pre_monomorphic_stub() {
693
    return pre_monomorphic_stub(isolate(), strict_mode());
694
  }
695
  static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
696
                                           StrictModeFlag strict_mode) {
697
    if (strict_mode == kStrictMode) {
698
      return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
699
    } else {
700
      return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
701
    }
702
  }
703
  virtual Handle<Code> slow_stub() const {
704
    if (strict_mode() == kStrictMode) {
705
      return isolate()->builtins()->KeyedStoreIC_Slow_Strict();
706
    } else {
707
      return isolate()->builtins()->KeyedStoreIC_Slow();
708
    }
709
  }
710
  virtual Handle<Code> megamorphic_stub() {
711
    if (strict_mode() == kStrictMode) {
712
      return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
713
    } else {
714
      return isolate()->builtins()->KeyedStoreIC_Generic();
715
    }
716
  }
717

    
718
  Handle<Code> StoreElementStub(Handle<JSObject> receiver,
719
                                KeyedAccessStoreMode store_mode);
720

    
721
 private:
722
  void set_target(Code* code) {
723
    // Strict mode must be preserved across IC patching.
724
    ASSERT(Code::GetStrictMode(code->extra_ic_state()) == strict_mode());
725
    IC::set_target(code);
726
  }
727

    
728
  // Stub accessors.
729
  static Handle<Code> initialize_stub(Isolate* isolate,
730
                                      StrictModeFlag strict_mode) {
731
    if (strict_mode == kStrictMode) {
732
      return isolate->builtins()->KeyedStoreIC_Initialize_Strict();
733
    } else {
734
      return isolate->builtins()->KeyedStoreIC_Initialize();
735
    }
736
  }
737

    
738
  virtual Handle<Code> generic_stub() const {
739
    if (strict_mode() == kStrictMode) {
740
      return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
741
    } else {
742
      return isolate()->builtins()->KeyedStoreIC_Generic();
743
    }
744
  }
745

    
746
  Handle<Code> non_strict_arguments_stub() {
747
    return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
748
  }
749

    
750
  static void Clear(Isolate* isolate, Address address, Code* target);
751

    
752
  KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
753
                                    Handle<Object> key,
754
                                    Handle<Object> value);
755

    
756
  Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
757
                                     KeyedAccessStoreMode store_mode);
758

    
759
  friend class IC;
760
};
761

    
762

    
763
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
764
class BinaryOpIC: public IC {
765
 public:
766
  enum TypeInfo {
767
    UNINITIALIZED,
768
    SMI,
769
    INT32,
770
    NUMBER,
771
    ODDBALL,
772
    STRING,  // Only used for addition operation.
773
    GENERIC
774
  };
775

    
776
  explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
777

    
778
  static Builtins::JavaScript TokenToJSBuiltin(Token::Value op);
779

    
780
  static const char* GetName(TypeInfo type_info);
781

    
782
  MUST_USE_RESULT MaybeObject* Transition(Handle<Object> left,
783
                                          Handle<Object> right);
784
};
785

    
786

    
787
class CompareIC: public IC {
788
 public:
789
  // The type/state lattice is defined by the following inequations:
790
  //   UNINITIALIZED < ...
791
  //   ... < GENERIC
792
  //   SMI < NUMBER
793
  //   INTERNALIZED_STRING < STRING
794
  //   KNOWN_OBJECT < OBJECT
795
  enum State {
796
    UNINITIALIZED,
797
    SMI,
798
    NUMBER,
799
    STRING,
800
    INTERNALIZED_STRING,
801
    UNIQUE_NAME,    // Symbol or InternalizedString
802
    OBJECT,         // JSObject
803
    KNOWN_OBJECT,   // JSObject with specific map (faster check)
804
    GENERIC
805
  };
806

    
807
  static State NewInputState(State old_state, Handle<Object> value);
808

    
809
  static Handle<Type> StateToType(Isolate* isolate,
810
                                  State state,
811
                                  Handle<Map> map = Handle<Map>());
812

    
813
  static void StubInfoToType(int stub_minor_key,
814
                             Handle<Type>* left_type,
815
                             Handle<Type>* right_type,
816
                             Handle<Type>* overall_type,
817
                             Handle<Map> map,
818
                             Isolate* isolate);
819

    
820
  CompareIC(Isolate* isolate, Token::Value op)
821
      : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
822

    
823
  // Update the inline cache for the given operands.
824
  void UpdateCaches(Handle<Object> x, Handle<Object> y);
825

    
826

    
827
  // Factory method for getting an uninitialized compare stub.
828
  static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op);
829

    
830
  // Helper function for computing the condition for a compare operation.
831
  static Condition ComputeCondition(Token::Value op);
832

    
833
  static const char* GetStateName(State state);
834

    
835
 private:
836
  static bool HasInlinedSmiCode(Address address);
837

    
838
  State TargetState(State old_state,
839
                    State old_left,
840
                    State old_right,
841
                    bool has_inlined_smi_code,
842
                    Handle<Object> x,
843
                    Handle<Object> y);
844

    
845
  bool strict() const { return op_ == Token::EQ_STRICT; }
846
  Condition GetCondition() const { return ComputeCondition(op_); }
847

    
848
  static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
849

    
850
  static void Clear(Isolate* isolate, Address address, Code* target);
851

    
852
  Token::Value op_;
853

    
854
  friend class IC;
855
};
856

    
857

    
858
class CompareNilIC: public IC {
859
 public:
860
  explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
861

    
862
  MUST_USE_RESULT MaybeObject* CompareNil(Handle<Object> object);
863

    
864
  static Handle<Code> GetUninitialized();
865

    
866
  static void Clear(Address address, Code* target);
867

    
868
  static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(NilValue nil,
869
                                                       Handle<Object> object);
870
};
871

    
872

    
873
class ToBooleanIC: public IC {
874
 public:
875
  explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
876

    
877
  MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state);
878
};
879

    
880

    
881
// Helper for BinaryOpIC and CompareIC.
882
enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
883
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
884

    
885
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
886
DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
887
DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
888
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
889
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
890
DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss);
891
DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
892
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
893

    
894

    
895
} }  // namespace v8::internal
896

    
897
#endif  // V8_IC_H_