OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 24 matching lines...) Expand all Loading... |
35 | 35 |
36 | 36 |
37 const int kMaxKeyedPolymorphism = 4; | 37 const int kMaxKeyedPolymorphism = 4; |
38 | 38 |
39 | 39 |
40 // IC_UTIL_LIST defines all utility functions called from generated | 40 // IC_UTIL_LIST defines all utility functions called from generated |
41 // inline caching code. The argument for the macro, ICU, is the function name. | 41 // inline caching code. The argument for the macro, ICU, is the function name. |
42 #define IC_UTIL_LIST(ICU) \ | 42 #define IC_UTIL_LIST(ICU) \ |
43 ICU(LoadIC_Miss) \ | 43 ICU(LoadIC_Miss) \ |
44 ICU(KeyedLoadIC_Miss) \ | 44 ICU(KeyedLoadIC_Miss) \ |
45 ICU(CallIC_Miss) \ | |
46 ICU(KeyedCallIC_Miss) \ | |
47 ICU(StoreIC_Miss) \ | 45 ICU(StoreIC_Miss) \ |
48 ICU(StoreIC_ArrayLength) \ | 46 ICU(StoreIC_ArrayLength) \ |
49 ICU(StoreIC_Slow) \ | 47 ICU(StoreIC_Slow) \ |
50 ICU(SharedStoreIC_ExtendStorage) \ | 48 ICU(SharedStoreIC_ExtendStorage) \ |
51 ICU(KeyedStoreIC_Miss) \ | 49 ICU(KeyedStoreIC_Miss) \ |
52 ICU(KeyedStoreIC_Slow) \ | 50 ICU(KeyedStoreIC_Slow) \ |
53 /* Utilities for IC stubs. */ \ | 51 /* Utilities for IC stubs. */ \ |
54 ICU(StoreCallbackProperty) \ | 52 ICU(StoreCallbackProperty) \ |
55 ICU(LoadPropertyWithInterceptorOnly) \ | 53 ICU(LoadPropertyWithInterceptorOnly) \ |
56 ICU(LoadPropertyWithInterceptorForLoad) \ | 54 ICU(LoadPropertyWithInterceptorForLoad) \ |
57 ICU(LoadPropertyWithInterceptorForCall) \ | 55 ICU(LoadPropertyWithInterceptorForCall) \ |
58 ICU(KeyedLoadPropertyWithInterceptor) \ | 56 ICU(KeyedLoadPropertyWithInterceptor) \ |
59 ICU(StoreInterceptorProperty) \ | 57 ICU(StoreInterceptorProperty) \ |
60 ICU(CompareIC_Miss) \ | 58 ICU(CompareIC_Miss) \ |
61 ICU(BinaryOpIC_Miss) \ | 59 ICU(BinaryOpIC_Miss) \ |
62 ICU(CompareNilIC_Miss) \ | 60 ICU(CompareNilIC_Miss) \ |
63 ICU(Unreachable) \ | 61 ICU(Unreachable) \ |
64 ICU(ToBooleanIC_Miss) | 62 ICU(ToBooleanIC_Miss) |
65 // | 63 // |
66 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC, | 64 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC. |
67 // and KeyedStoreIC. | |
68 // | 65 // |
69 class IC { | 66 class IC { |
70 public: | 67 public: |
71 // The ids for utility called from the generated code. | 68 // The ids for utility called from the generated code. |
72 enum UtilityId { | 69 enum UtilityId { |
73 #define CONST_NAME(name) k##name, | 70 #define CONST_NAME(name) k##name, |
74 IC_UTIL_LIST(CONST_NAME) | 71 IC_UTIL_LIST(CONST_NAME) |
75 #undef CONST_NAME | 72 #undef CONST_NAME |
76 kUtilityCount | 73 kUtilityCount |
77 }; | 74 }; |
(...skipping 29 matching lines...) Expand all Loading... |
107 static void Clear(Isolate* isolate, Address address); | 104 static void Clear(Isolate* isolate, Address address); |
108 | 105 |
109 #ifdef DEBUG | 106 #ifdef DEBUG |
110 bool IsLoadStub() const { | 107 bool IsLoadStub() const { |
111 return target()->is_load_stub() || target()->is_keyed_load_stub(); | 108 return target()->is_load_stub() || target()->is_keyed_load_stub(); |
112 } | 109 } |
113 | 110 |
114 bool IsStoreStub() const { | 111 bool IsStoreStub() const { |
115 return target()->is_store_stub() || target()->is_keyed_store_stub(); | 112 return target()->is_store_stub() || target()->is_keyed_store_stub(); |
116 } | 113 } |
117 | |
118 bool IsCallStub() const { | |
119 return target()->is_call_stub() || target()->is_keyed_call_stub(); | |
120 } | |
121 #endif | 114 #endif |
122 | 115 |
123 // Determines which map must be used for keeping the code stub. | 116 // Determines which map must be used for keeping the code stub. |
124 // These methods should not be called with undefined or null. | 117 // These methods should not be called with undefined or null. |
125 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object); | 118 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object); |
126 // TODO(verwaest): This currently returns a HeapObject rather than JSObject* | 119 // TODO(verwaest): This currently returns a HeapObject rather than JSObject* |
127 // since loading the IC for loading the length from strings are stored on | 120 // since loading the IC for loading the length from strings are stored on |
128 // the string map directly, rather than on the JSObject-typed prototype. | 121 // the string map directly, rather than on the JSObject-typed prototype. |
129 static inline HeapObject* GetCodeCacheHolder(Isolate* isolate, | 122 static inline HeapObject* GetCodeCacheHolder(Isolate* isolate, |
130 Object* object, | 123 Object* object, |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 | 270 |
278 Address address() const { return address_; } | 271 Address address() const { return address_; } |
279 | 272 |
280 IC::UtilityId id() const { return id_; } | 273 IC::UtilityId id() const { return id_; } |
281 private: | 274 private: |
282 Address address_; | 275 Address address_; |
283 IC::UtilityId id_; | 276 IC::UtilityId id_; |
284 }; | 277 }; |
285 | 278 |
286 | 279 |
287 class CallICBase: public IC { | |
288 public: | |
289 // Returns a JSFunction or a Failure. | |
290 MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object, | |
291 Handle<String> name); | |
292 | |
293 protected: | |
294 CallICBase(Code::Kind kind, Isolate* isolate) | |
295 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {} | |
296 | |
297 // Compute a monomorphic stub if possible, otherwise return a null handle. | |
298 Handle<Code> ComputeMonomorphicStub(LookupResult* lookup, | |
299 Handle<Object> object, | |
300 Handle<String> name); | |
301 | |
302 // Update the inline cache and the global stub cache based on the lookup | |
303 // result. | |
304 void UpdateCaches(LookupResult* lookup, | |
305 Handle<Object> object, | |
306 Handle<String> name); | |
307 | |
308 // Returns a JSFunction if the object can be called as a function, and | |
309 // patches the stack to be ready for the call. Otherwise, it returns the | |
310 // undefined value. | |
311 Handle<Object> TryCallAsFunction(Handle<Object> object); | |
312 | |
313 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object); | |
314 | |
315 static void Clear(Address address, Code* target); | |
316 | |
317 // Platform-specific code generation functions used by both call and | |
318 // keyed call. | |
319 static void GenerateMiss(MacroAssembler* masm, | |
320 int argc, | |
321 IC::UtilityId id, | |
322 ExtraICState extra_state); | |
323 | |
324 static void GenerateNormal(MacroAssembler* masm, int argc); | |
325 | |
326 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | |
327 int argc, | |
328 Code::Kind kind, | |
329 ExtraICState extra_state); | |
330 | |
331 virtual Handle<Code> megamorphic_stub(); | |
332 virtual Handle<Code> pre_monomorphic_stub(); | |
333 | |
334 Code::Kind kind_; | |
335 | |
336 friend class IC; | |
337 }; | |
338 | |
339 | |
340 class CallIC: public CallICBase { | |
341 public: | |
342 explicit CallIC(Isolate* isolate) | |
343 : CallICBase(Code::CALL_IC, isolate) { | |
344 ASSERT(target()->is_call_stub()); | |
345 } | |
346 | |
347 // Code generator routines. | |
348 static void GenerateInitialize(MacroAssembler* masm, | |
349 int argc, | |
350 ExtraICState extra_state) { | |
351 GenerateMiss(masm, argc, extra_state); | |
352 } | |
353 | |
354 static void GenerateMiss(MacroAssembler* masm, | |
355 int argc, | |
356 ExtraICState extra_state) { | |
357 CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state); | |
358 } | |
359 | |
360 static void GenerateMegamorphic(MacroAssembler* masm, | |
361 int argc, | |
362 ExtraICState extra_ic_state); | |
363 | |
364 static void GenerateNormal(MacroAssembler* masm, int argc) { | |
365 CallICBase::GenerateNormal(masm, argc); | |
366 GenerateMiss(masm, argc, kNoExtraICState); | |
367 } | |
368 bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object); | |
369 }; | |
370 | |
371 | |
372 class KeyedCallIC: public CallICBase { | |
373 public: | |
374 explicit KeyedCallIC(Isolate* isolate) | |
375 : CallICBase(Code::KEYED_CALL_IC, isolate) { | |
376 ASSERT(target()->is_keyed_call_stub()); | |
377 } | |
378 | |
379 MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object, | |
380 Handle<Object> key); | |
381 | |
382 // Code generator routines. | |
383 static void GenerateInitialize(MacroAssembler* masm, int argc) { | |
384 GenerateMiss(masm, argc); | |
385 } | |
386 | |
387 static void GenerateMiss(MacroAssembler* masm, int argc) { | |
388 CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss, | |
389 kNoExtraICState); | |
390 } | |
391 | |
392 static void GenerateMegamorphic(MacroAssembler* masm, int argc); | |
393 static void GenerateNormal(MacroAssembler* masm, int argc); | |
394 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc); | |
395 }; | |
396 | |
397 | |
398 class LoadIC: public IC { | 280 class LoadIC: public IC { |
399 public: | 281 public: |
400 // ExtraICState bits | 282 // ExtraICState bits |
401 class Contextual: public BitField<ContextualMode, 0, 1> {}; | 283 class ContextualModeBits: public BitField<ContextualMode, 0, 1> {}; |
402 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); | 284 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); |
403 | 285 |
404 static ExtraICState ComputeExtraICState(ContextualMode mode) { | 286 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { |
405 return Contextual::encode(mode); | 287 return ContextualModeBits::encode(contextual_mode); |
406 } | 288 } |
407 | 289 |
408 static ContextualMode GetContextualMode(ExtraICState state) { | 290 static ContextualMode GetContextualMode(ExtraICState state) { |
409 return Contextual::decode(state); | 291 return ContextualModeBits::decode(state); |
410 } | 292 } |
411 | 293 |
412 ContextualMode contextual_mode() const { | 294 ContextualMode contextual_mode() const { |
413 return Contextual::decode(extra_ic_state()); | 295 return ContextualModeBits::decode(extra_ic_state()); |
414 } | 296 } |
415 | 297 |
416 explicit LoadIC(FrameDepth depth, Isolate* isolate) | 298 explicit LoadIC(FrameDepth depth, Isolate* isolate) |
417 : IC(depth, isolate) { | 299 : IC(depth, isolate) { |
418 ASSERT(IsLoadStub()); | 300 ASSERT(IsLoadStub()); |
419 } | 301 } |
420 | 302 |
421 // Returns if this IC is for contextual (no explicit receiver) | 303 // Returns if this IC is for contextual (no explicit receiver) |
422 // access to properties. | 304 // access to properties. |
423 bool IsUndeclaredGlobal(Handle<Object> receiver) { | 305 bool IsUndeclaredGlobal(Handle<Object> receiver) { |
424 if (receiver->IsGlobalObject()) { | 306 if (receiver->IsGlobalObject()) { |
425 return contextual_mode() == CONTEXTUAL; | 307 return contextual_mode() == CONTEXTUAL; |
426 } else { | 308 } else { |
427 ASSERT(contextual_mode() != CONTEXTUAL); | 309 ASSERT(contextual_mode() != CONTEXTUAL); |
428 return false; | 310 return false; |
429 } | 311 } |
430 } | 312 } |
431 | 313 |
432 // Code generator routines. | 314 // Code generator routines. |
433 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } | 315 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } |
434 static void GeneratePreMonomorphic(MacroAssembler* masm) { | 316 static void GeneratePreMonomorphic(MacroAssembler* masm) { |
435 GenerateMiss(masm); | 317 GenerateMiss(masm); |
436 } | 318 } |
437 static void GenerateMiss(MacroAssembler* masm); | 319 static void GenerateMiss(MacroAssembler* masm); |
438 static void GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode); | 320 static void GenerateMegamorphic(MacroAssembler* masm, |
| 321 ExtraICState extra_state); |
439 static void GenerateNormal(MacroAssembler* masm); | 322 static void GenerateNormal(MacroAssembler* masm); |
440 static void GenerateRuntimeGetProperty(MacroAssembler* masm); | 323 static void GenerateRuntimeGetProperty(MacroAssembler* masm); |
441 | 324 |
442 static Handle<Code> initialize_stub(Isolate* isolate, ContextualMode mode); | 325 static Handle<Code> initialize_stub(Isolate* isolate, |
| 326 ExtraICState extra_state); |
443 | 327 |
444 MUST_USE_RESULT MaybeObject* Load(Handle<Object> object, | 328 MUST_USE_RESULT MaybeObject* Load(Handle<Object> object, |
445 Handle<String> name); | 329 Handle<String> name); |
446 | 330 |
447 protected: | 331 protected: |
448 virtual Code::Kind kind() const { return Code::LOAD_IC; } | 332 virtual Code::Kind kind() const { return Code::LOAD_IC; } |
449 | 333 |
450 void set_target(Code* code) { | 334 void set_target(Code* code) { |
451 // The contextual mode must be preserved across IC patching. | 335 // The contextual mode must be preserved across IC patching. |
452 ASSERT(GetContextualMode(code->extra_ic_state()) == | 336 ASSERT(GetContextualMode(code->extra_ic_state()) == |
(...skipping 16 matching lines...) Expand all Loading... |
469 | 353 |
470 virtual Handle<Code> CompileHandler(LookupResult* lookup, | 354 virtual Handle<Code> CompileHandler(LookupResult* lookup, |
471 Handle<Object> object, | 355 Handle<Object> object, |
472 Handle<String> name, | 356 Handle<String> name, |
473 Handle<Object> unused, | 357 Handle<Object> unused, |
474 InlineCacheHolderFlag cache_holder); | 358 InlineCacheHolderFlag cache_holder); |
475 | 359 |
476 private: | 360 private: |
477 // Stub accessors. | 361 // Stub accessors. |
478 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, | 362 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, |
479 ContextualMode mode); | 363 ExtraICState exstra_state); |
480 | 364 |
481 virtual Handle<Code> pre_monomorphic_stub() { | 365 virtual Handle<Code> pre_monomorphic_stub() { |
482 return pre_monomorphic_stub(isolate(), contextual_mode()); | 366 return pre_monomorphic_stub(isolate(), extra_ic_state()); |
483 } | 367 } |
484 | 368 |
485 Handle<Code> SimpleFieldLoad(int offset, | 369 Handle<Code> SimpleFieldLoad(int offset, |
486 bool inobject = true, | 370 bool inobject = true, |
487 Representation representation = | 371 Representation representation = |
488 Representation::Tagged()); | 372 Representation::Tagged()); |
489 | 373 |
490 static void Clear(Isolate* isolate, Address address, Code* target); | 374 static void Clear(Isolate* isolate, Address address, Code* target); |
491 | 375 |
492 friend class IC; | 376 friend class IC; |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 | 879 |
996 | 880 |
997 // Helper for BinaryOpIC and CompareIC. | 881 // Helper for BinaryOpIC and CompareIC. |
998 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; | 882 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; |
999 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); | 883 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); |
1000 | 884 |
1001 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure); | 885 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure); |
1002 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure); | 886 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure); |
1003 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss); | 887 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss); |
1004 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure); | 888 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure); |
1005 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure); | |
1006 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss); | 889 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss); |
1007 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss); | 890 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss); |
1008 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite); | 891 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite); |
1009 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss); | 892 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss); |
1010 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss); | 893 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss); |
1011 | 894 |
1012 | 895 |
1013 } } // namespace v8::internal | 896 } } // namespace v8::internal |
1014 | 897 |
1015 #endif // V8_IC_H_ | 898 #endif // V8_IC_H_ |
OLD | NEW |