~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/third_party/v8/src/ic.h

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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(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)                       \
 
60
  ICU(UnaryOp_Patch)                                  \
 
61
  ICU(BinaryOp_Patch)                                 \
 
62
  ICU(CompareIC_Miss)                                 \
 
63
  ICU(ToBoolean_Patch)
 
64
//
 
65
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
 
66
// and KeyedStoreIC.
 
67
//
 
68
class IC {
 
69
 public:
 
70
  // The ids for utility called from the generated code.
 
71
  enum UtilityId {
 
72
  #define CONST_NAME(name) k##name,
 
73
    IC_UTIL_LIST(CONST_NAME)
 
74
  #undef CONST_NAME
 
75
    kUtilityCount
 
76
  };
 
77
 
 
78
  // Looks up the address of the named utility.
 
79
  static Address AddressFromUtilityId(UtilityId id);
 
80
 
 
81
  // Alias the inline cache state type to make the IC code more readable.
 
82
  typedef InlineCacheState State;
 
83
 
 
84
  // The IC code is either invoked with no extra frames on the stack
 
85
  // or with a single extra frame for supporting calls.
 
86
  enum FrameDepth {
 
87
    NO_EXTRA_FRAME = 0,
 
88
    EXTRA_CALL_FRAME = 1
 
89
  };
 
90
 
 
91
  // Construct the IC structure with the given number of extra
 
92
  // JavaScript frames on the stack.
 
93
  IC(FrameDepth depth, Isolate* isolate);
 
94
  virtual ~IC() {}
 
95
 
 
96
  // Get the call-site target; used for determining the state.
 
97
  Code* target() const { return GetTargetAtAddress(address()); }
 
98
  inline Address address() const;
 
99
 
 
100
  virtual bool IsGeneric() const { return false; }
 
101
 
 
102
  // Compute the current IC state based on the target stub, receiver and name.
 
103
  static State StateFrom(Code* target, Object* receiver, Object* name);
 
104
 
 
105
  // Clear the inline cache to initial state.
 
106
  static void Clear(Address address);
 
107
 
 
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();
 
112
 
 
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();
 
118
    } else {
 
119
      ASSERT(!SlowIsContextual());
 
120
      return false;
 
121
    }
 
122
  }
 
123
 
 
124
  bool SlowIsContextual() {
 
125
    return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
 
126
  }
 
127
 
 
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,
 
131
                                                            JSObject* holder);
 
132
  static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
 
133
                                                            JSObject* holder);
 
134
  static inline JSObject* GetCodeCacheHolder(Object* object,
 
135
                                             InlineCacheHolderFlag holder);
 
136
 
 
137
 protected:
 
138
  Address fp() const { return fp_; }
 
139
  Address pc() const { return *pc_address_; }
 
140
  Isolate* isolate() const { return isolate_; }
 
141
 
 
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;
 
146
#endif
 
147
 
 
148
  // Set the call-site target.
 
149
  void set_target(Code* code) { SetTargetAtAddress(address(), code); }
 
150
 
 
151
#ifdef DEBUG
 
152
  char TransitionMarkFromState(IC::State state);
 
153
 
 
154
  void TraceIC(const char* type,
 
155
               Handle<Object> name,
 
156
               State old_state,
 
157
               Code* new_target);
 
158
#endif
 
159
 
 
160
  Failure* TypeError(const char* type,
 
161
                     Handle<Object> object,
 
162
                     Handle<Object> key);
 
163
  Failure* ReferenceError(const char* type, Handle<String> name);
 
164
 
 
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);
 
169
 
 
170
 private:
 
171
  // Frame pointer for the frame that uses (calls) the IC.
 
172
  Address fp_;
 
173
 
 
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_;
 
179
 
 
180
  Isolate* isolate_;
 
181
 
 
182
  DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
 
183
};
 
184
 
 
185
 
 
186
// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
 
187
// cannot make forward declarations to an enum.
 
188
class IC_Utility {
 
189
 public:
 
190
  explicit IC_Utility(IC::UtilityId id)
 
191
    : address_(IC::AddressFromUtilityId(id)), id_(id) {}
 
192
 
 
193
  Address address() const { return address_; }
 
194
 
 
195
  IC::UtilityId id() const { return id_; }
 
196
 private:
 
197
  Address address_;
 
198
  IC::UtilityId id_;
 
199
};
 
200
 
 
201
 
 
202
class CallICBase: public IC {
 
203
 public:
 
204
  class Contextual: public BitField<bool, 0, 1> {};
 
205
  class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
 
206
 
 
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);
 
212
 
 
213
 protected:
 
214
  CallICBase(Code::Kind kind, Isolate* isolate)
 
215
      : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
 
216
 
 
217
  bool TryUpdateExtraICState(LookupResult* lookup,
 
218
                             Handle<Object> object,
 
219
                             Code::ExtraICState* extra_ic_state);
 
220
 
 
221
  // Compute a monomorphic stub if possible, otherwise return a null handle.
 
222
  Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
 
223
                                      State state,
 
224
                                      Code::ExtraICState extra_state,
 
225
                                      Handle<Object> object,
 
226
                                      Handle<String> name);
 
227
 
 
228
  // Update the inline cache and the global stub cache based on the lookup
 
229
  // result.
 
230
  void UpdateCaches(LookupResult* lookup,
 
231
                    State state,
 
232
                    Code::ExtraICState extra_ic_state,
 
233
                    Handle<Object> object,
 
234
                    Handle<String> name);
 
235
 
 
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
 
238
  // undefined value.
 
239
  Handle<Object> TryCallAsFunction(Handle<Object> object);
 
240
 
 
241
  void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
 
242
 
 
243
  static void Clear(Address address, Code* target);
 
244
 
 
245
  // Platform-specific code generation functions used by both call and
 
246
  // keyed call.
 
247
  static void GenerateMiss(MacroAssembler* masm,
 
248
                           int argc,
 
249
                           IC::UtilityId id,
 
250
                           Code::ExtraICState extra_state);
 
251
 
 
252
  static void GenerateNormal(MacroAssembler* masm, int argc);
 
253
 
 
254
  static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
 
255
                                            int argc,
 
256
                                            Code::Kind kind,
 
257
                                            Code::ExtraICState extra_state);
 
258
 
 
259
  Code::Kind kind_;
 
260
 
 
261
  friend class IC;
 
262
};
 
263
 
 
264
 
 
265
class CallIC: public CallICBase {
 
266
 public:
 
267
  explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
 
268
    ASSERT(target()->is_call_stub());
 
269
  }
 
270
 
 
271
  // Code generator routines.
 
272
  static void GenerateInitialize(MacroAssembler* masm,
 
273
                                 int argc,
 
274
                                 Code::ExtraICState extra_state) {
 
275
    GenerateMiss(masm, argc, extra_state);
 
276
  }
 
277
 
 
278
  static void GenerateMiss(MacroAssembler* masm,
 
279
                           int argc,
 
280
                           Code::ExtraICState extra_state) {
 
281
    CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
 
282
  }
 
283
 
 
284
  static void GenerateMegamorphic(MacroAssembler* masm,
 
285
                                  int argc,
 
286
                                  Code::ExtraICState extra_ic_state);
 
287
 
 
288
  static void GenerateNormal(MacroAssembler* masm, int argc) {
 
289
    CallICBase::GenerateNormal(masm, argc);
 
290
    GenerateMiss(masm, argc, Code::kNoExtraICState);
 
291
  }
 
292
};
 
293
 
 
294
 
 
295
class KeyedCallIC: public CallICBase {
 
296
 public:
 
297
  explicit KeyedCallIC(Isolate* isolate)
 
298
      : CallICBase(Code::KEYED_CALL_IC, isolate) {
 
299
    ASSERT(target()->is_keyed_call_stub());
 
300
  }
 
301
 
 
302
  MUST_USE_RESULT MaybeObject* LoadFunction(State state,
 
303
                                            Handle<Object> object,
 
304
                                            Handle<Object> key);
 
305
 
 
306
  // Code generator routines.
 
307
  static void GenerateInitialize(MacroAssembler* masm, int argc) {
 
308
    GenerateMiss(masm, argc);
 
309
  }
 
310
 
 
311
  static void GenerateMiss(MacroAssembler* masm, int argc) {
 
312
    CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
 
313
                             Code::kNoExtraICState);
 
314
  }
 
315
 
 
316
  static void GenerateMegamorphic(MacroAssembler* masm, int argc);
 
317
  static void GenerateNormal(MacroAssembler* masm, int argc);
 
318
  static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
 
319
};
 
320
 
 
321
 
 
322
class LoadIC: public IC {
 
323
 public:
 
324
  explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
 
325
    ASSERT(target()->is_load_stub());
 
326
  }
 
327
 
 
328
  MUST_USE_RESULT MaybeObject* Load(State state,
 
329
                                    Handle<Object> object,
 
330
                                    Handle<String> name);
 
331
 
 
332
  // Code generator routines.
 
333
  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
 
334
  static void GeneratePreMonomorphic(MacroAssembler* masm) {
 
335
    GenerateMiss(masm);
 
336
  }
 
337
  static void GenerateMiss(MacroAssembler* masm);
 
338
  static void GenerateMegamorphic(MacroAssembler* masm);
 
339
  static void GenerateNormal(MacroAssembler* masm);
 
340
 
 
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);
 
346
 
 
347
 private:
 
348
  // Update the inline cache and the global stub cache based on the
 
349
  // lookup result.
 
350
  void UpdateCaches(LookupResult* lookup,
 
351
                    State state,
 
352
                    Handle<Object> object,
 
353
                    Handle<String> name);
 
354
 
 
355
  // Stub accessors.
 
356
  Handle<Code> megamorphic_stub() {
 
357
    return isolate()->builtins()->LoadIC_Megamorphic();
 
358
  }
 
359
  static Code* initialize_stub() {
 
360
    return Isolate::Current()->builtins()->builtin(
 
361
        Builtins::kLoadIC_Initialize);
 
362
  }
 
363
  Handle<Code> pre_monomorphic_stub() {
 
364
    return isolate()->builtins()->LoadIC_PreMonomorphic();
 
365
  }
 
366
 
 
367
  static void Clear(Address address, Code* target);
 
368
 
 
369
  friend class IC;
 
370
};
 
371
 
 
372
 
 
373
class KeyedIC: public IC {
 
374
 public:
 
375
  enum StubKind {
 
376
    LOAD,
 
377
    STORE_NO_TRANSITION,
 
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
 
391
  };
 
392
 
 
393
  static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
 
394
      STORE_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);
 
404
 
 
405
  explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
 
406
  virtual ~KeyedIC() {}
 
407
 
 
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;
 
413
  }
 
414
 
 
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) +
 
419
                                        kGrowICDelta);
 
420
    }
 
421
    return stub_kind;
 
422
  }
 
423
 
 
424
  virtual Handle<Code> GetElementStubWithoutMapCheck(
 
425
      bool is_js_array,
 
426
      ElementsKind elements_kind,
 
427
      KeyedAccessGrowMode grow_mode) = 0;
 
428
 
 
429
 protected:
 
430
  virtual Handle<Code> string_stub() {
 
431
    return Handle<Code>::null();
 
432
  }
 
433
 
 
434
  virtual Code::Kind kind() const = 0;
 
435
 
 
436
  Handle<Code> ComputeStub(Handle<JSObject> receiver,
 
437
                           StubKind stub_kind,
 
438
                           StrictModeFlag strict_mode,
 
439
                           Handle<Code> default_stub);
 
440
 
 
441
  virtual Handle<Code> ComputePolymorphicStub(
 
442
      MapHandleList* receiver_maps,
 
443
      StrictModeFlag strict_mode,
 
444
      KeyedAccessGrowMode grow_mode) = 0;
 
445
 
 
446
  Handle<Code> ComputeMonomorphicStubWithoutMapCheck(
 
447
      Handle<Map> receiver_map,
 
448
      StrictModeFlag strict_mode,
 
449
      KeyedAccessGrowMode grow_mode);
 
450
 
 
451
 private:
 
452
  void GetReceiverMapsForStub(Handle<Code> stub, MapHandleList* result);
 
453
 
 
454
  Handle<Code> ComputeMonomorphicStub(Handle<Map> receiver_map,
 
455
                                      StubKind stub_kind,
 
456
                                      StrictModeFlag strict_mode,
 
457
                                      Handle<Code> default_stub);
 
458
 
 
459
  Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
 
460
                                     StubKind stub_kind);
 
461
 
 
462
  static bool IsTransitionStubKind(StubKind stub_kind) {
 
463
    return stub_kind > STORE_NO_TRANSITION &&
 
464
        stub_kind != STORE_AND_GROW_NO_TRANSITION;
 
465
  }
 
466
 
 
467
  static bool IsGrowStubKind(StubKind stub_kind) {
 
468
    return stub_kind >= STORE_AND_GROW_NO_TRANSITION;
 
469
  }
 
470
 
 
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;
 
475
  }
 
476
};
 
477
 
 
478
 
 
479
class KeyedLoadIC: public KeyedIC {
 
480
 public:
 
481
  explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
 
482
    ASSERT(target()->is_keyed_load_stub());
 
483
  }
 
484
 
 
485
  MUST_USE_RESULT MaybeObject* Load(State state,
 
486
                                    Handle<Object> object,
 
487
                                    Handle<Object> key,
 
488
                                    bool force_generic_stub);
 
489
 
 
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);
 
495
  }
 
496
  static void GeneratePreMonomorphic(MacroAssembler* masm) {
 
497
    GenerateMiss(masm, false);
 
498
  }
 
499
  static void GenerateGeneric(MacroAssembler* masm);
 
500
  static void GenerateString(MacroAssembler* masm);
 
501
  static void GenerateIndexedInterceptor(MacroAssembler* masm);
 
502
  static void GenerateNonStrictArguments(MacroAssembler* masm);
 
503
 
 
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
 
507
  // map checks.
 
508
  static const int kSlowCaseBitFieldMask =
 
509
      (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
 
510
 
 
511
  virtual Handle<Code> GetElementStubWithoutMapCheck(
 
512
      bool is_js_array,
 
513
      ElementsKind elements_kind,
 
514
      KeyedAccessGrowMode grow_mode);
 
515
 
 
516
  virtual bool IsGeneric() const {
 
517
    return target() == *generic_stub();
 
518
  }
 
519
 
 
520
 protected:
 
521
  virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
 
522
 
 
523
  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
 
524
                                              StrictModeFlag strict_mode,
 
525
                                              KeyedAccessGrowMode grow_mode);
 
526
 
 
527
  virtual Handle<Code> string_stub() {
 
528
    return isolate()->builtins()->KeyedLoadIC_String();
 
529
  }
 
530
 
 
531
 private:
 
532
  // Update the inline cache.
 
533
  void UpdateCaches(LookupResult* lookup,
 
534
                    State state,
 
535
                    Handle<Object> object,
 
536
                    Handle<String> name);
 
537
 
 
538
  // Stub accessors.
 
539
  static Code* initialize_stub() {
 
540
    return Isolate::Current()->builtins()->builtin(
 
541
        Builtins::kKeyedLoadIC_Initialize);
 
542
  }
 
543
  Handle<Code> megamorphic_stub() {
 
544
    return isolate()->builtins()->KeyedLoadIC_Generic();
 
545
  }
 
546
  Handle<Code> generic_stub() const {
 
547
    return isolate()->builtins()->KeyedLoadIC_Generic();
 
548
  }
 
549
  Handle<Code> pre_monomorphic_stub() {
 
550
    return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
 
551
  }
 
552
  Handle<Code> indexed_interceptor_stub() {
 
553
    return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
 
554
  }
 
555
  Handle<Code> non_strict_arguments_stub() {
 
556
    return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
 
557
  }
 
558
 
 
559
  static void Clear(Address address, Code* target);
 
560
 
 
561
  friend class IC;
 
562
};
 
563
 
 
564
 
 
565
class StoreIC: public IC {
 
566
 public:
 
567
  explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
 
568
    ASSERT(target()->is_store_stub());
 
569
  }
 
570
 
 
571
  MUST_USE_RESULT MaybeObject* Store(State state,
 
572
                                     StrictModeFlag strict_mode,
 
573
                                     Handle<Object> object,
 
574
                                     Handle<String> name,
 
575
                                     Handle<Object> value);
 
576
 
 
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);
 
586
 
 
587
 private:
 
588
  // Update the inline cache and the global stub cache based on the
 
589
  // lookup result.
 
590
  void UpdateCaches(LookupResult* lookup,
 
591
                    State state,
 
592
                    StrictModeFlag strict_mode,
 
593
                    Handle<JSObject> receiver,
 
594
                    Handle<String> name,
 
595
                    Handle<Object> value);
 
596
 
 
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);
 
602
  }
 
603
 
 
604
  // Stub accessors.
 
605
  Code* megamorphic_stub() {
 
606
    return isolate()->builtins()->builtin(
 
607
        Builtins::kStoreIC_Megamorphic);
 
608
  }
 
609
  Code* megamorphic_stub_strict() {
 
610
    return isolate()->builtins()->builtin(
 
611
        Builtins::kStoreIC_Megamorphic_Strict);
 
612
  }
 
613
  static Code* initialize_stub() {
 
614
    return Isolate::Current()->builtins()->builtin(
 
615
        Builtins::kStoreIC_Initialize);
 
616
  }
 
617
  static Code* initialize_stub_strict() {
 
618
    return Isolate::Current()->builtins()->builtin(
 
619
        Builtins::kStoreIC_Initialize_Strict);
 
620
  }
 
621
  Handle<Code> global_proxy_stub() {
 
622
    return isolate()->builtins()->StoreIC_GlobalProxy();
 
623
  }
 
624
  Handle<Code> global_proxy_stub_strict() {
 
625
    return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
 
626
  }
 
627
 
 
628
  static void Clear(Address address, Code* target);
 
629
 
 
630
  friend class IC;
 
631
};
 
632
 
 
633
 
 
634
class KeyedStoreIC: public KeyedIC {
 
635
 public:
 
636
  explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
 
637
    ASSERT(target()->is_keyed_store_stub());
 
638
  }
 
639
 
 
640
  MUST_USE_RESULT MaybeObject* Store(State state,
 
641
                                   StrictModeFlag strict_mode,
 
642
                                     Handle<Object> object,
 
643
                                     Handle<Object> name,
 
644
                                     Handle<Object> value,
 
645
                                     bool force_generic);
 
646
 
 
647
  // Code generators for stub routines.  Only called once at startup.
 
648
  static void GenerateInitialize(MacroAssembler* masm) {
 
649
    GenerateMiss(masm, false);
 
650
  }
 
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);
 
659
 
 
660
  virtual Handle<Code> GetElementStubWithoutMapCheck(
 
661
      bool is_js_array,
 
662
      ElementsKind elements_kind,
 
663
      KeyedAccessGrowMode grow_mode);
 
664
 
 
665
  virtual bool IsGeneric() const {
 
666
    return target() == *generic_stub() ||
 
667
        target() == *generic_stub_strict();
 
668
  }
 
669
 
 
670
 protected:
 
671
  virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
 
672
 
 
673
  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
 
674
                                              StrictModeFlag strict_mode,
 
675
                                              KeyedAccessGrowMode grow_mode);
 
676
 
 
677
  private:
 
678
  // Update the inline cache.
 
679
  void UpdateCaches(LookupResult* lookup,
 
680
                    State state,
 
681
                    StrictModeFlag strict_mode,
 
682
                    Handle<JSObject> receiver,
 
683
                    Handle<String> name,
 
684
                    Handle<Object> value);
 
685
 
 
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);
 
691
  }
 
692
 
 
693
  // Stub accessors.
 
694
  static Code* initialize_stub() {
 
695
    return Isolate::Current()->builtins()->builtin(
 
696
        Builtins::kKeyedStoreIC_Initialize);
 
697
  }
 
698
  static Code* initialize_stub_strict() {
 
699
    return Isolate::Current()->builtins()->builtin(
 
700
        Builtins::kKeyedStoreIC_Initialize_Strict);
 
701
  }
 
702
  Handle<Code> megamorphic_stub() {
 
703
    return isolate()->builtins()->KeyedStoreIC_Generic();
 
704
  }
 
705
  Handle<Code> megamorphic_stub_strict() {
 
706
    return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
 
707
  }
 
708
  Handle<Code> generic_stub() const {
 
709
    return isolate()->builtins()->KeyedStoreIC_Generic();
 
710
  }
 
711
  Handle<Code> generic_stub_strict() const {
 
712
    return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
 
713
  }
 
714
  Handle<Code> non_strict_arguments_stub() {
 
715
    return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
 
716
  }
 
717
 
 
718
  static void Clear(Address address, Code* target);
 
719
 
 
720
  StubKind GetStubKind(Handle<JSObject> receiver,
 
721
                       Handle<Object> key,
 
722
                       Handle<Object> value);
 
723
 
 
724
  friend class IC;
 
725
};
 
726
 
 
727
 
 
728
class UnaryOpIC: public IC {
 
729
 public:
 
730
  // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
 
731
  // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
 
732
  enum TypeInfo {
 
733
    UNINITIALIZED,
 
734
    SMI,
 
735
    HEAP_NUMBER,
 
736
    GENERIC
 
737
  };
 
738
 
 
739
  explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
 
740
 
 
741
  void patch(Code* code);
 
742
 
 
743
  static const char* GetName(TypeInfo type_info);
 
744
 
 
745
  static State ToState(TypeInfo type_info);
 
746
 
 
747
  static TypeInfo GetTypeInfo(Handle<Object> operand);
 
748
 
 
749
  static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
 
750
};
 
751
 
 
752
 
 
753
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
 
754
class BinaryOpIC: public IC {
 
755
 public:
 
756
  enum TypeInfo {
 
757
    UNINITIALIZED,
 
758
    SMI,
 
759
    INT32,
 
760
    HEAP_NUMBER,
 
761
    ODDBALL,
 
762
    BOTH_STRING,  // Only used for addition operation.
 
763
    STRING,  // Only used for addition operation.  At least one string operand.
 
764
    GENERIC
 
765
  };
 
766
 
 
767
  explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
 
768
 
 
769
  void patch(Code* code);
 
770
 
 
771
  static const char* GetName(TypeInfo type_info);
 
772
 
 
773
  static State ToState(TypeInfo type_info);
 
774
 
 
775
  static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
 
776
 
 
777
  static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
 
778
};
 
779
 
 
780
 
 
781
class CompareIC: public IC {
 
782
 public:
 
783
  enum State {
 
784
    UNINITIALIZED,
 
785
    SMIS,
 
786
    HEAP_NUMBERS,
 
787
    SYMBOLS,
 
788
    STRINGS,
 
789
    OBJECTS,
 
790
    KNOWN_OBJECTS,
 
791
    GENERIC
 
792
  };
 
793
 
 
794
  CompareIC(Isolate* isolate, Token::Value op)
 
795
      : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
 
796
 
 
797
  // Update the inline cache for the given operands.
 
798
  void UpdateCaches(Handle<Object> x, Handle<Object> y);
 
799
 
 
800
  // Factory method for getting an uninitialized compare stub.
 
801
  static Handle<Code> GetUninitialized(Token::Value op);
 
802
 
 
803
  // Helper function for computing the condition for a compare operation.
 
804
  static Condition ComputeCondition(Token::Value op);
 
805
 
 
806
  // Helper function for determining the state of a compare IC.
 
807
  static State ComputeState(Code* target);
 
808
 
 
809
  // Helper function for determining the operation a compare IC is for.
 
810
  static Token::Value ComputeOperation(Code* target);
 
811
 
 
812
  static const char* GetStateName(State state);
 
813
 
 
814
 private:
 
815
  State TargetState(State state, bool has_inlined_smi_code,
 
816
                    Handle<Object> x, Handle<Object> y);
 
817
 
 
818
  bool strict() const { return op_ == Token::EQ_STRICT; }
 
819
  Condition GetCondition() const { return ComputeCondition(op_); }
 
820
  State GetState() { return ComputeState(target()); }
 
821
 
 
822
  static Code* GetRawUninitialized(Token::Value op);
 
823
 
 
824
  static void Clear(Address address, Code* target);
 
825
 
 
826
  Token::Value op_;
 
827
 
 
828
  friend class IC;
 
829
};
 
830
 
 
831
 
 
832
class ToBooleanIC: public IC {
 
833
 public:
 
834
  explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
 
835
 
 
836
  void patch(Code* code);
 
837
};
 
838
 
 
839
 
 
840
// Helper for BinaryOpIC and CompareIC.
 
841
enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
 
842
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
 
843
 
 
844
} }  // namespace v8::internal
 
845
 
 
846
#endif  // V8_IC_H_