OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_STUB_CACHE_H_ | 5 #ifndef V8_STUB_CACHE_H_ |
6 #define V8_STUB_CACHE_H_ | 6 #define V8_STUB_CACHE_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 class StubCache { | 47 class StubCache { |
48 public: | 48 public: |
49 struct Entry { | 49 struct Entry { |
50 Name* key; | 50 Name* key; |
51 Code* value; | 51 Code* value; |
52 Map* map; | 52 Map* map; |
53 }; | 53 }; |
54 | 54 |
55 void Initialize(); | 55 void Initialize(); |
56 | 56 |
57 Handle<JSObject> StubHolder(Handle<JSObject> receiver, | |
58 Handle<JSObject> holder); | |
59 | |
60 Handle<Code> FindIC(Handle<Name> name, Handle<Map> stub_holder_map, | |
61 Code::Kind kind, | |
62 ExtraICState extra_state = kNoExtraICState, | |
63 CacheHolderFlag cache_holder = kCacheOnReceiver); | |
64 | |
65 Handle<Code> FindHandler(Handle<Name> name, Handle<Map> map, Code::Kind kind, | |
66 CacheHolderFlag cache_holder, Code::StubType type); | |
67 | |
68 Handle<Code> ComputeMonomorphicIC(Code::Kind kind, | 57 Handle<Code> ComputeMonomorphicIC(Code::Kind kind, |
69 Handle<Name> name, | 58 Handle<Name> name, |
70 Handle<HeapType> type, | 59 Handle<HeapType> type, |
71 Handle<Code> handler, | 60 Handle<Code> handler, |
72 ExtraICState extra_ic_state); | 61 ExtraICState extra_ic_state); |
73 | 62 |
74 Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<HeapType> type); | 63 Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<HeapType> type); |
75 | 64 |
76 Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map); | 65 Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map); |
77 | 66 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); | 260 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); |
272 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); | 261 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); |
273 DECLARE_RUNTIME_FUNCTION(StoreInterceptorProperty); | 262 DECLARE_RUNTIME_FUNCTION(StoreInterceptorProperty); |
274 DECLARE_RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor); | 263 DECLARE_RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor); |
275 | 264 |
276 | 265 |
277 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; | 266 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; |
278 enum IcCheckType { ELEMENT, PROPERTY }; | 267 enum IcCheckType { ELEMENT, PROPERTY }; |
279 | 268 |
280 | 269 |
281 // The stub compilers compile stubs for the stub cache. | 270 class PropertyAccessCompiler BASE_EMBEDDED { |
282 class StubCompiler BASE_EMBEDDED { | |
283 public: | 271 public: |
284 explicit StubCompiler(Isolate* isolate, | 272 static Builtins::Name MissBuiltin(Code::Kind kind) { |
285 ExtraICState extra_ic_state = kNoExtraICState) | 273 switch (kind) { |
286 : isolate_(isolate), extra_ic_state_(extra_ic_state), | 274 case Code::LOAD_IC: |
287 masm_(isolate, NULL, 256) { } | 275 return Builtins::kLoadIC_Miss; |
| 276 case Code::STORE_IC: |
| 277 return Builtins::kStoreIC_Miss; |
| 278 case Code::KEYED_LOAD_IC: |
| 279 return Builtins::kKeyedLoadIC_Miss; |
| 280 case Code::KEYED_STORE_IC: |
| 281 return Builtins::kKeyedStoreIC_Miss; |
| 282 default: |
| 283 UNREACHABLE(); |
| 284 } |
| 285 return Builtins::kLoadIC_Miss; |
| 286 } |
| 287 |
| 288 static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name); |
| 289 |
| 290 protected: |
| 291 PropertyAccessCompiler(Isolate* isolate, Code::Kind kind, |
| 292 ExtraICState extra_ic_state, |
| 293 CacheHolderFlag cache_holder) |
| 294 : registers_(GetCallingConvention(kind)), |
| 295 kind_(kind), |
| 296 cache_holder_(cache_holder), |
| 297 isolate_(isolate), |
| 298 extra_ic_state_(extra_ic_state), |
| 299 masm_(isolate, NULL, 256) {} |
| 300 |
| 301 Code::Kind kind() const { return kind_; } |
| 302 CacheHolderFlag cache_holder() const { return cache_holder_; } |
| 303 ExtraICState extra_state() const { return extra_ic_state_; } |
| 304 MacroAssembler* masm() { return &masm_; } |
| 305 Isolate* isolate() const { return isolate_; } |
| 306 Heap* heap() const { return isolate()->heap(); } |
| 307 Factory* factory() const { return isolate()->factory(); } |
| 308 |
| 309 Register receiver() const { return registers_[0]; } |
| 310 Register name() const { return registers_[1]; } |
| 311 Register scratch1() const { return registers_[2]; } |
| 312 Register scratch2() const { return registers_[3]; } |
| 313 Register scratch3() const { return registers_[4]; } |
| 314 |
| 315 // Calling convention between indexed store IC and handler. |
| 316 Register transition_map() const { return scratch1(); } |
| 317 |
| 318 static Register* GetCallingConvention(Code::Kind); |
| 319 static Register* load_calling_convention(); |
| 320 static Register* store_calling_convention(); |
| 321 static Register* keyed_store_calling_convention(); |
| 322 |
| 323 Register* registers_; |
| 324 |
| 325 static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code); |
| 326 |
| 327 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name); |
| 328 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name); |
| 329 |
| 330 private: |
| 331 Code::Kind kind_; |
| 332 CacheHolderFlag cache_holder_; |
| 333 |
| 334 Isolate* isolate_; |
| 335 const ExtraICState extra_ic_state_; |
| 336 MacroAssembler masm_; |
| 337 }; |
| 338 |
| 339 |
| 340 class PropertyICCompiler : public PropertyAccessCompiler { |
| 341 public: |
| 342 PropertyICCompiler(Isolate* isolate, Code::Kind kind, |
| 343 ExtraICState extra_ic_state = kNoExtraICState, |
| 344 CacheHolderFlag cache_holder = kCacheOnReceiver) |
| 345 : PropertyAccessCompiler(isolate, kind, extra_ic_state, cache_holder) {} |
| 346 |
| 347 static Handle<Code> Find(Handle<Name> name, Handle<Map> stub_holder_map, |
| 348 Code::Kind kind, |
| 349 ExtraICState extra_state = kNoExtraICState, |
| 350 CacheHolderFlag cache_holder = kCacheOnReceiver); |
288 | 351 |
289 Handle<Code> CompileLoadInitialize(Code::Flags flags); | 352 Handle<Code> CompileLoadInitialize(Code::Flags flags); |
290 Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags); | 353 Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags); |
291 Handle<Code> CompileLoadMegamorphic(Code::Flags flags); | 354 Handle<Code> CompileLoadMegamorphic(Code::Flags flags); |
292 | |
293 Handle<Code> CompileStoreInitialize(Code::Flags flags); | 355 Handle<Code> CompileStoreInitialize(Code::Flags flags); |
294 Handle<Code> CompileStorePreMonomorphic(Code::Flags flags); | 356 Handle<Code> CompileStorePreMonomorphic(Code::Flags flags); |
295 Handle<Code> CompileStoreGeneric(Code::Flags flags); | 357 Handle<Code> CompileStoreGeneric(Code::Flags flags); |
296 Handle<Code> CompileStoreMegamorphic(Code::Flags flags); | 358 Handle<Code> CompileStoreMegamorphic(Code::Flags flags); |
297 | 359 |
298 // Static functions for generating parts of stubs. | 360 Handle<Code> CompileMonomorphic(Handle<HeapType> type, Handle<Code> handler, |
299 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 361 Handle<Name> name, IcCheckType check); |
300 int index, | 362 |
301 Register prototype); | 363 Handle<Code> CompilePolymorphic(TypeHandleList* types, |
| 364 CodeHandleList* handlers, Handle<Name> name, |
| 365 Code::StubType type, IcCheckType check); |
| 366 |
| 367 Handle<Code> CompileIndexedStoreMonomorphic(Handle<Map> receiver_map, |
| 368 KeyedAccessStoreMode store_mode); |
| 369 Handle<Code> CompileIndexedStorePolymorphic(MapHandleList* receiver_maps, |
| 370 KeyedAccessStoreMode store_mode); |
| 371 |
| 372 private: |
| 373 bool IncludesNumberType(TypeHandleList* types); |
| 374 |
| 375 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name, |
| 376 InlineCacheState state = MONOMORPHIC); |
| 377 |
| 378 Logger::LogEventsAndTags log_kind(Handle<Code> code) { |
| 379 if (kind() == Code::LOAD_IC) { |
| 380 return code->ic_state() == MONOMORPHIC ? Logger::LOAD_IC_TAG |
| 381 : Logger::LOAD_POLYMORPHIC_IC_TAG; |
| 382 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 383 return code->ic_state() == MONOMORPHIC |
| 384 ? Logger::KEYED_LOAD_IC_TAG |
| 385 : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG; |
| 386 } else if (kind() == Code::STORE_IC) { |
| 387 return code->ic_state() == MONOMORPHIC ? Logger::STORE_IC_TAG |
| 388 : Logger::STORE_POLYMORPHIC_IC_TAG; |
| 389 } else { |
| 390 ASSERT_EQ(Code::KEYED_STORE_IC, kind()); |
| 391 return code->ic_state() == MONOMORPHIC |
| 392 ? Logger::KEYED_STORE_IC_TAG |
| 393 : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG; |
| 394 } |
| 395 } |
| 396 |
| 397 Handle<Code> CompileIndexedStorePolymorphic(MapHandleList* receiver_maps, |
| 398 CodeHandleList* handler_stubs, |
| 399 MapHandleList* transitioned_maps); |
| 400 }; |
| 401 |
| 402 |
| 403 class PropertyHandlerCompiler : public PropertyAccessCompiler { |
| 404 public: |
| 405 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind, |
| 406 CacheHolderFlag cache_holder, Code::StubType type); |
| 407 |
| 408 protected: |
| 409 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, |
| 410 ExtraICState extra_ic_state, |
| 411 CacheHolderFlag cache_holder) |
| 412 : PropertyAccessCompiler(isolate, kind, extra_ic_state, cache_holder) {} |
| 413 |
| 414 virtual ~PropertyHandlerCompiler() {} |
| 415 |
| 416 virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg, |
| 417 Handle<JSObject> holder, Handle<Name> name, |
| 418 Label* miss) { |
| 419 UNREACHABLE(); |
| 420 return receiver(); |
| 421 } |
| 422 |
| 423 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); } |
| 424 |
| 425 Register Frontend(Handle<HeapType> type, Register object_reg, |
| 426 Handle<JSObject> holder, Handle<Name> name); |
| 427 |
| 428 // TODO(verwaest): Make non-static. |
| 429 static void GenerateFastApiCall(MacroAssembler* masm, |
| 430 const CallOptimization& optimization, |
| 431 Handle<Map> receiver_map, Register receiver, |
| 432 Register scratch, bool is_store, int argc, |
| 433 Register* values); |
302 | 434 |
303 // Helper function used to check that the dictionary doesn't contain | 435 // Helper function used to check that the dictionary doesn't contain |
304 // the property. This function may return false negatives, so miss_label | 436 // the property. This function may return false negatives, so miss_label |
305 // must always call a backup property check that is complete. | 437 // must always call a backup property check that is complete. |
306 // This function is safe to call if the receiver has fast properties. | 438 // This function is safe to call if the receiver has fast properties. |
307 // Name must be unique and receiver must be a heap object. | 439 // Name must be unique and receiver must be a heap object. |
308 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 440 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
309 Label* miss_label, | 441 Label* miss_label, |
310 Register receiver, | 442 Register receiver, |
311 Handle<Name> name, | 443 Handle<Name> name, |
312 Register r0, | 444 Register r0, |
313 Register r1); | 445 Register r1); |
314 | 446 |
315 // Generates prototype loading code that uses the objects from the | |
316 // context we were in when this function was called. If the context | |
317 // has changed, a jump to miss is performed. This ties the generated | |
318 // code to a particular context and so must not be used in cases | |
319 // where the generated code is not allowed to have references to | |
320 // objects from a context. | |
321 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm, | |
322 int index, | |
323 Register prototype, | |
324 Label* miss); | |
325 | |
326 static void GenerateFastPropertyLoad(MacroAssembler* masm, | |
327 Register dst, | |
328 Register src, | |
329 bool inobject, | |
330 int index, | |
331 Representation representation); | |
332 | |
333 static void GenerateLoadArrayLength(MacroAssembler* masm, | |
334 Register receiver, | |
335 Register scratch, | |
336 Label* miss_label); | |
337 | |
338 static void GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
339 Register receiver, | |
340 Register scratch1, | |
341 Register scratch2, | |
342 Label* miss_label); | |
343 | |
344 // Generate code to check that a global property cell is empty. Create | 447 // Generate code to check that a global property cell is empty. Create |
345 // the property cell at compilation time if no cell exists for the | 448 // the property cell at compilation time if no cell exists for the |
346 // property. | 449 // property. |
347 static void GenerateCheckPropertyCell(MacroAssembler* masm, | 450 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
348 Handle<JSGlobalObject> global, | 451 Handle<JSGlobalObject> global, |
349 Handle<Name> name, | 452 Handle<Name> name, |
350 Register scratch, | 453 Register scratch, |
351 Label* miss); | 454 Label* miss); |
352 | 455 |
353 static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name); | |
354 | |
355 // Generates code that verifies that the property holder has not changed | 456 // Generates code that verifies that the property holder has not changed |
356 // (checking maps of objects in the prototype chain for fast and global | 457 // (checking maps of objects in the prototype chain for fast and global |
357 // objects or doing negative lookup for slow objects, ensures that the | 458 // objects or doing negative lookup for slow objects, ensures that the |
358 // property cells for global objects are still empty) and checks that the map | 459 // property cells for global objects are still empty) and checks that the map |
359 // of the holder has not changed. If necessary the function also generates | 460 // of the holder has not changed. If necessary the function also generates |
360 // code for security check in case of global object holders. Helps to make | 461 // code for security check in case of global object holders. Helps to make |
361 // sure that the current IC is still valid. | 462 // sure that the current IC is still valid. |
362 // | 463 // |
363 // The scratch and holder registers are always clobbered, but the object | 464 // The scratch and holder registers are always clobbered, but the object |
364 // register is only clobbered if it the same as the holder register. The | 465 // register is only clobbered if it the same as the holder register. The |
365 // function returns a register containing the holder - either object_reg or | 466 // function returns a register containing the holder - either object_reg or |
366 // holder_reg. | 467 // holder_reg. |
367 Register CheckPrototypes(Handle<HeapType> type, | 468 Register CheckPrototypes(Handle<HeapType> type, |
368 Register object_reg, | 469 Register object_reg, |
369 Handle<JSObject> holder, | 470 Handle<JSObject> holder, |
370 Register holder_reg, | 471 Register holder_reg, |
371 Register scratch1, | 472 Register scratch1, |
372 Register scratch2, | 473 Register scratch2, |
373 Handle<Name> name, | 474 Handle<Name> name, |
374 Label* miss, | 475 Label* miss, |
375 PrototypeCheckType check = CHECK_ALL_MAPS); | 476 PrototypeCheckType check = CHECK_ALL_MAPS); |
376 | 477 |
377 static void GenerateFastApiCall(MacroAssembler* masm, | 478 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name); |
378 const CallOptimization& optimization, | |
379 Handle<Map> receiver_map, | |
380 Register receiver, | |
381 Register scratch, | |
382 bool is_store, | |
383 int argc, | |
384 Register* values); | |
385 | |
386 protected: | |
387 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name); | |
388 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name); | |
389 | |
390 ExtraICState extra_state() { return extra_ic_state_; } | |
391 | |
392 MacroAssembler* masm() { return &masm_; } | |
393 | |
394 static void LookupPostInterceptor(Handle<JSObject> holder, | |
395 Handle<Name> name, | |
396 LookupResult* lookup); | |
397 | |
398 Isolate* isolate() { return isolate_; } | |
399 Heap* heap() { return isolate()->heap(); } | |
400 Factory* factory() { return isolate()->factory(); } | |
401 | |
402 static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code); | |
403 | |
404 private: | |
405 Isolate* isolate_; | |
406 const ExtraICState extra_ic_state_; | |
407 MacroAssembler masm_; | |
408 }; | 479 }; |
409 | 480 |
410 | 481 |
411 enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS }; | 482 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { |
| 483 public: |
| 484 NamedLoadHandlerCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC, |
| 485 ExtraICState extra_ic_state = kNoExtraICState, |
| 486 CacheHolderFlag cache_holder = kCacheOnReceiver) |
| 487 : PropertyHandlerCompiler(isolate, kind, extra_ic_state, cache_holder) {} |
412 | 488 |
413 | 489 virtual ~NamedLoadHandlerCompiler() {} |
414 class BaseLoadStoreStubCompiler: public StubCompiler { | |
415 public: | |
416 BaseLoadStoreStubCompiler(Isolate* isolate, Code::Kind kind, | |
417 ExtraICState extra_ic_state = kNoExtraICState, | |
418 CacheHolderFlag cache_holder = kCacheOnReceiver) | |
419 : StubCompiler(isolate, extra_ic_state), | |
420 kind_(kind), | |
421 cache_holder_(cache_holder) { | |
422 InitializeRegisters(); | |
423 } | |
424 virtual ~BaseLoadStoreStubCompiler() { } | |
425 | |
426 Handle<Code> CompileMonomorphicIC(Handle<HeapType> type, | |
427 Handle<Code> handler, | |
428 Handle<Name> name); | |
429 | |
430 Handle<Code> CompilePolymorphicIC(TypeHandleList* types, | |
431 CodeHandleList* handlers, | |
432 Handle<Name> name, | |
433 Code::StubType type, | |
434 IcCheckType check); | |
435 | |
436 static Builtins::Name MissBuiltin(Code::Kind kind) { | |
437 switch (kind) { | |
438 case Code::LOAD_IC: return Builtins::kLoadIC_Miss; | |
439 case Code::STORE_IC: return Builtins::kStoreIC_Miss; | |
440 case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss; | |
441 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss; | |
442 default: UNREACHABLE(); | |
443 } | |
444 return Builtins::kLoadIC_Miss; | |
445 } | |
446 | |
447 protected: | |
448 virtual Register HandlerFrontendHeader(Handle<HeapType> type, | |
449 Register object_reg, | |
450 Handle<JSObject> holder, | |
451 Handle<Name> name, | |
452 Label* miss) = 0; | |
453 | |
454 virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss) = 0; | |
455 | |
456 Register HandlerFrontend(Handle<HeapType> type, | |
457 Register object_reg, | |
458 Handle<JSObject> holder, | |
459 Handle<Name> name); | |
460 | |
461 Handle<Code> GetCode(Code::Kind kind, | |
462 Code::StubType type, | |
463 Handle<Name> name); | |
464 | |
465 Handle<Code> GetICCode(Code::Kind kind, | |
466 Code::StubType type, | |
467 Handle<Name> name, | |
468 InlineCacheState state = MONOMORPHIC); | |
469 Code::Kind kind() { return kind_; } | |
470 | |
471 Logger::LogEventsAndTags log_kind(Handle<Code> code) { | |
472 if (!code->is_inline_cache_stub()) return Logger::STUB_TAG; | |
473 if (kind_ == Code::LOAD_IC) { | |
474 return code->ic_state() == MONOMORPHIC | |
475 ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG; | |
476 } else if (kind_ == Code::KEYED_LOAD_IC) { | |
477 return code->ic_state() == MONOMORPHIC | |
478 ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG; | |
479 } else if (kind_ == Code::STORE_IC) { | |
480 return code->ic_state() == MONOMORPHIC | |
481 ? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG; | |
482 } else { | |
483 return code->ic_state() == MONOMORPHIC | |
484 ? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG; | |
485 } | |
486 } | |
487 | |
488 Register receiver() { return registers_[0]; } | |
489 Register name() { return registers_[1]; } | |
490 Register scratch1() { return registers_[2]; } | |
491 Register scratch2() { return registers_[3]; } | |
492 Register scratch3() { return registers_[4]; } | |
493 | |
494 void InitializeRegisters(); | |
495 | |
496 bool IncludesNumberType(TypeHandleList* types); | |
497 | |
498 Code::Kind kind_; | |
499 CacheHolderFlag cache_holder_; | |
500 Register* registers_; | |
501 }; | |
502 | |
503 | |
504 class LoadStubCompiler: public BaseLoadStoreStubCompiler { | |
505 public: | |
506 LoadStubCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC, | |
507 ExtraICState extra_ic_state = kNoExtraICState, | |
508 CacheHolderFlag cache_holder = kCacheOnReceiver) | |
509 : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state, cache_holder) { | |
510 } | |
511 virtual ~LoadStubCompiler() { } | |
512 static Register* registers(); | |
513 | 490 |
514 Handle<Code> CompileLoadField(Handle<HeapType> type, | 491 Handle<Code> CompileLoadField(Handle<HeapType> type, |
515 Handle<JSObject> holder, | 492 Handle<JSObject> holder, |
516 Handle<Name> name, | 493 Handle<Name> name, |
517 FieldIndex index, | 494 FieldIndex index, |
518 Representation representation); | 495 Representation representation); |
519 | 496 |
520 Handle<Code> CompileLoadCallback(Handle<HeapType> type, | 497 Handle<Code> CompileLoadCallback(Handle<HeapType> type, |
521 Handle<JSObject> holder, | 498 Handle<JSObject> holder, |
522 Handle<Name> name, | 499 Handle<Name> name, |
(...skipping 11 matching lines...) Expand all Loading... |
534 | 511 |
535 Handle<Code> CompileLoadInterceptor(Handle<HeapType> type, | 512 Handle<Code> CompileLoadInterceptor(Handle<HeapType> type, |
536 Handle<JSObject> holder, | 513 Handle<JSObject> holder, |
537 Handle<Name> name); | 514 Handle<Name> name); |
538 | 515 |
539 Handle<Code> CompileLoadViaGetter(Handle<HeapType> type, | 516 Handle<Code> CompileLoadViaGetter(Handle<HeapType> type, |
540 Handle<JSObject> holder, | 517 Handle<JSObject> holder, |
541 Handle<Name> name, | 518 Handle<Name> name, |
542 Handle<JSFunction> getter); | 519 Handle<JSFunction> getter); |
543 | 520 |
544 static void GenerateLoadViaGetter(MacroAssembler* masm, | |
545 Handle<HeapType> type, | |
546 Register receiver, | |
547 Handle<JSFunction> getter); | |
548 | |
549 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) { | |
550 GenerateLoadViaGetter( | |
551 masm, Handle<HeapType>::null(), no_reg, Handle<JSFunction>()); | |
552 } | |
553 | |
554 Handle<Code> CompileLoadNonexistent(Handle<HeapType> type, | 521 Handle<Code> CompileLoadNonexistent(Handle<HeapType> type, |
555 Handle<JSObject> last, | 522 Handle<JSObject> last, |
556 Handle<Name> name); | 523 Handle<Name> name); |
557 | 524 |
558 Handle<Code> CompileLoadGlobal(Handle<HeapType> type, | 525 Handle<Code> CompileLoadGlobal(Handle<HeapType> type, |
559 Handle<GlobalObject> holder, | 526 Handle<GlobalObject> holder, |
560 Handle<PropertyCell> cell, | 527 Handle<PropertyCell> cell, |
561 Handle<Name> name, | 528 Handle<Name> name, |
562 bool is_dont_delete); | 529 bool is_dont_delete); |
563 | 530 |
564 protected: | 531 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type, |
565 ContextualMode contextual_mode() { | 532 Register receiver, |
566 return LoadIC::GetContextualMode(extra_state()); | 533 Handle<JSFunction> getter); |
| 534 |
| 535 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) { |
| 536 GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg, |
| 537 Handle<JSFunction>()); |
567 } | 538 } |
568 | 539 |
569 virtual Register HandlerFrontendHeader(Handle<HeapType> type, | 540 static void GenerateLoadFunctionPrototype(MacroAssembler* masm, |
570 Register object_reg, | 541 Register receiver, |
571 Handle<JSObject> holder, | 542 Register scratch1, |
572 Handle<Name> name, | 543 Register scratch2, |
573 Label* miss); | 544 Label* miss_label); |
574 | 545 |
575 virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss); | 546 protected: |
| 547 virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg, |
| 548 Handle<JSObject> holder, Handle<Name> name, |
| 549 Label* miss); |
576 | 550 |
577 Register CallbackHandlerFrontend(Handle<HeapType> type, | 551 virtual void FrontendFooter(Handle<Name> name, Label* miss); |
578 Register object_reg, | 552 |
579 Handle<JSObject> holder, | 553 private: |
580 Handle<Name> name, | 554 Register CallbackFrontend(Handle<HeapType> type, Register object_reg, |
581 Handle<Object> callback); | 555 Handle<JSObject> holder, Handle<Name> name, |
582 void NonexistentHandlerFrontend(Handle<HeapType> type, | 556 Handle<Object> callback); |
583 Handle<JSObject> last, | 557 void NonexistentFrontend(Handle<HeapType> type, Handle<JSObject> last, |
584 Handle<Name> name); | 558 Handle<Name> name); |
585 | 559 |
586 void GenerateLoadField(Register reg, | 560 void GenerateLoadField(Register reg, |
587 Handle<JSObject> holder, | 561 Handle<JSObject> holder, |
588 FieldIndex field, | 562 FieldIndex field, |
589 Representation representation); | 563 Representation representation); |
590 void GenerateLoadConstant(Handle<Object> value); | 564 void GenerateLoadConstant(Handle<Object> value); |
591 void GenerateLoadCallback(Register reg, | 565 void GenerateLoadCallback(Register reg, |
592 Handle<ExecutableAccessorInfo> callback); | 566 Handle<ExecutableAccessorInfo> callback); |
593 void GenerateLoadCallback(const CallOptimization& call_optimization, | 567 void GenerateLoadCallback(const CallOptimization& call_optimization, |
594 Handle<Map> receiver_map); | 568 Handle<Map> receiver_map); |
595 void GenerateLoadInterceptor(Register holder_reg, | 569 void GenerateLoadInterceptor(Register holder_reg, |
596 Handle<Object> object, | 570 Handle<Object> object, |
597 Handle<JSObject> holder, | 571 Handle<JSObject> holder, |
598 LookupResult* lookup, | 572 LookupResult* lookup, |
599 Handle<Name> name); | 573 Handle<Name> name); |
600 void GenerateLoadPostInterceptor(Register reg, | 574 void GenerateLoadPostInterceptor(Register reg, |
601 Handle<JSObject> interceptor_holder, | 575 Handle<JSObject> interceptor_holder, |
602 Handle<Name> name, | 576 Handle<Name> name, |
603 LookupResult* lookup); | 577 LookupResult* lookup); |
604 | 578 |
605 private: | 579 // Generates prototype loading code that uses the objects from the |
| 580 // context we were in when this function was called. If the context |
| 581 // has changed, a jump to miss is performed. This ties the generated |
| 582 // code to a particular context and so must not be used in cases |
| 583 // where the generated code is not allowed to have references to |
| 584 // objects from a context. |
| 585 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm, |
| 586 int index, |
| 587 Register prototype, |
| 588 Label* miss); |
| 589 |
| 590 |
606 Register scratch4() { return registers_[5]; } | 591 Register scratch4() { return registers_[5]; } |
607 friend class BaseLoadStoreStubCompiler; | |
608 }; | 592 }; |
609 | 593 |
610 | 594 |
611 class KeyedLoadStubCompiler : public StubCompiler { | 595 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { |
612 public: | 596 public: |
613 KeyedLoadStubCompiler(Isolate* isolate, | 597 NamedStoreHandlerCompiler(Isolate* isolate, Code::Kind kind = Code::STORE_IC) |
614 ExtraICState extra_ic_state = kNoExtraICState) | 598 // Handlers do not use strict mode. |
615 : StubCompiler(isolate, extra_ic_state) { | 599 : PropertyHandlerCompiler(isolate, kind, kNoExtraICState, |
616 registers_ = LoadStubCompiler::registers(); | 600 kCacheOnReceiver) {} |
617 } | |
618 | 601 |
619 Handle<Code> CompileLoadElement(Handle<Map> receiver_map); | 602 virtual ~NamedStoreHandlerCompiler() {} |
620 | |
621 void CompileElementHandlers(MapHandleList* receiver_maps, | |
622 CodeHandleList* handlers); | |
623 | |
624 static void GenerateLoadDictionaryElement(MacroAssembler* masm); | |
625 | |
626 Register receiver() { return registers_[0]; } | |
627 Register name() { return registers_[1]; } | |
628 Register scratch1() { return registers_[2]; } | |
629 Register scratch2() { return registers_[3]; } | |
630 Register scratch3() { return registers_[4]; } | |
631 | |
632 private: | |
633 static Register* registers(); | |
634 Register* registers_; | |
635 }; | |
636 | |
637 | |
638 class StoreStubCompiler: public BaseLoadStoreStubCompiler { | |
639 public: | |
640 StoreStubCompiler(Isolate* isolate, | |
641 ExtraICState extra_ic_state, | |
642 Code::Kind kind = Code::STORE_IC) | |
643 : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state) {} | |
644 | |
645 virtual ~StoreStubCompiler() { } | |
646 | 603 |
647 Handle<Code> CompileStoreTransition(Handle<JSObject> object, | 604 Handle<Code> CompileStoreTransition(Handle<JSObject> object, |
648 LookupResult* lookup, | 605 LookupResult* lookup, |
649 Handle<Map> transition, | 606 Handle<Map> transition, |
650 Handle<Name> name); | 607 Handle<Name> name); |
651 | 608 |
652 Handle<Code> CompileStoreField(Handle<JSObject> object, | 609 Handle<Code> CompileStoreField(Handle<JSObject> object, |
653 LookupResult* lookup, | 610 LookupResult* lookup, |
654 Handle<Name> name); | 611 Handle<Name> name); |
655 | 612 |
656 Handle<Code> CompileStoreArrayLength(Handle<JSObject> object, | 613 Handle<Code> CompileStoreArrayLength(Handle<JSObject> object, |
657 LookupResult* lookup, | 614 LookupResult* lookup, |
658 Handle<Name> name); | 615 Handle<Name> name); |
659 | 616 |
| 617 Handle<Code> CompileStoreCallback(Handle<JSObject> object, |
| 618 Handle<JSObject> holder, Handle<Name> name, |
| 619 Handle<ExecutableAccessorInfo> callback); |
| 620 |
| 621 Handle<Code> CompileStoreCallback(Handle<JSObject> object, |
| 622 Handle<JSObject> holder, Handle<Name> name, |
| 623 const CallOptimization& call_optimization); |
| 624 |
| 625 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, |
| 626 Handle<JSObject> holder, Handle<Name> name, |
| 627 Handle<JSFunction> setter); |
| 628 |
| 629 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object, |
| 630 Handle<Name> name); |
| 631 |
| 632 |
| 633 static void GenerateStoreViaSetter(MacroAssembler* masm, |
| 634 Handle<HeapType> type, Register receiver, |
| 635 Handle<JSFunction> setter); |
| 636 |
| 637 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) { |
| 638 GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg, |
| 639 Handle<JSFunction>()); |
| 640 } |
| 641 |
| 642 protected: |
| 643 virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg, |
| 644 Handle<JSObject> holder, Handle<Name> name, |
| 645 Label* miss); |
| 646 |
| 647 virtual void FrontendFooter(Handle<Name> name, Label* miss); |
| 648 void GenerateRestoreName(MacroAssembler* masm, Label* label, |
| 649 Handle<Name> name); |
| 650 |
| 651 private: |
660 void GenerateStoreArrayLength(); | 652 void GenerateStoreArrayLength(); |
661 | 653 |
662 void GenerateNegativeHolderLookup(MacroAssembler* masm, | 654 void GenerateNegativeHolderLookup(MacroAssembler* masm, |
663 Handle<JSObject> holder, | 655 Handle<JSObject> holder, |
664 Register holder_reg, | 656 Register holder_reg, |
665 Handle<Name> name, | 657 Handle<Name> name, |
666 Label* miss); | 658 Label* miss); |
667 | 659 |
668 void GenerateStoreTransition(MacroAssembler* masm, | 660 void GenerateStoreTransition(MacroAssembler* masm, |
669 Handle<JSObject> object, | 661 Handle<JSObject> object, |
(...skipping 12 matching lines...) Expand all Loading... |
682 void GenerateStoreField(MacroAssembler* masm, | 674 void GenerateStoreField(MacroAssembler* masm, |
683 Handle<JSObject> object, | 675 Handle<JSObject> object, |
684 LookupResult* lookup, | 676 LookupResult* lookup, |
685 Register receiver_reg, | 677 Register receiver_reg, |
686 Register name_reg, | 678 Register name_reg, |
687 Register value_reg, | 679 Register value_reg, |
688 Register scratch1, | 680 Register scratch1, |
689 Register scratch2, | 681 Register scratch2, |
690 Label* miss_label); | 682 Label* miss_label); |
691 | 683 |
692 Handle<Code> CompileStoreCallback(Handle<JSObject> object, | |
693 Handle<JSObject> holder, | |
694 Handle<Name> name, | |
695 Handle<ExecutableAccessorInfo> callback); | |
696 | |
697 Handle<Code> CompileStoreCallback(Handle<JSObject> object, | |
698 Handle<JSObject> holder, | |
699 Handle<Name> name, | |
700 const CallOptimization& call_optimization); | |
701 | |
702 static void GenerateStoreViaSetter(MacroAssembler* masm, | |
703 Handle<HeapType> type, | |
704 Register receiver, | |
705 Handle<JSFunction> setter); | |
706 | |
707 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) { | |
708 GenerateStoreViaSetter( | |
709 masm, Handle<HeapType>::null(), no_reg, Handle<JSFunction>()); | |
710 } | |
711 | |
712 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, | |
713 Handle<JSObject> holder, | |
714 Handle<Name> name, | |
715 Handle<JSFunction> setter); | |
716 | |
717 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object, | |
718 Handle<Name> name); | |
719 | |
720 static Builtins::Name SlowBuiltin(Code::Kind kind) { | 684 static Builtins::Name SlowBuiltin(Code::Kind kind) { |
721 switch (kind) { | 685 switch (kind) { |
722 case Code::STORE_IC: return Builtins::kStoreIC_Slow; | 686 case Code::STORE_IC: return Builtins::kStoreIC_Slow; |
723 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow; | 687 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow; |
724 default: UNREACHABLE(); | 688 default: UNREACHABLE(); |
725 } | 689 } |
726 return Builtins::kStoreIC_Slow; | 690 return Builtins::kStoreIC_Slow; |
727 } | 691 } |
728 | 692 |
729 protected: | |
730 virtual Register HandlerFrontendHeader(Handle<HeapType> type, | |
731 Register object_reg, | |
732 Handle<JSObject> holder, | |
733 Handle<Name> name, | |
734 Label* miss); | |
735 | |
736 virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss); | |
737 void GenerateRestoreName(MacroAssembler* masm, | |
738 Label* label, | |
739 Handle<Name> name); | |
740 | |
741 private: | |
742 static Register* registers(); | |
743 static Register value(); | 693 static Register value(); |
744 friend class BaseLoadStoreStubCompiler; | |
745 }; | 694 }; |
746 | 695 |
747 | 696 |
748 class KeyedStoreStubCompiler: public StoreStubCompiler { | 697 class IndexedHandlerCompiler : public PropertyHandlerCompiler { |
749 public: | 698 public: |
750 KeyedStoreStubCompiler(Isolate* isolate, | 699 IndexedHandlerCompiler(Isolate* isolate, |
751 ExtraICState extra_ic_state) | 700 ExtraICState extra_ic_state = kNoExtraICState) |
752 : StoreStubCompiler(isolate, extra_ic_state, Code::KEYED_STORE_IC) {} | 701 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC, extra_ic_state, |
| 702 kCacheOnReceiver) {} |
753 | 703 |
754 Handle<Code> CompileStoreElement(Handle<Map> receiver_map); | 704 virtual ~IndexedHandlerCompiler() {} |
755 | 705 |
756 Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps, | 706 void CompileElementHandlers(MapHandleList* receiver_maps, |
757 CodeHandleList* handler_stubs, | 707 CodeHandleList* handlers); |
758 MapHandleList* transitioned_maps); | |
759 | 708 |
760 Handle<Code> CompileStoreElementPolymorphic(MapHandleList* receiver_maps); | 709 static void GenerateLoadDictionaryElement(MacroAssembler* masm); |
761 | |
762 static void GenerateStoreDictionaryElement(MacroAssembler* masm); | 710 static void GenerateStoreDictionaryElement(MacroAssembler* masm); |
763 | |
764 private: | |
765 static Register* registers(); | |
766 | |
767 KeyedAccessStoreMode store_mode() { | |
768 return KeyedStoreIC::GetKeyedAccessStoreMode(extra_state()); | |
769 } | |
770 | |
771 Register transition_map() { return scratch1(); } | |
772 | |
773 friend class BaseLoadStoreStubCompiler; | |
774 }; | 711 }; |
775 | 712 |
776 | 713 |
777 // Holds information about possible function call optimizations. | 714 // Holds information about possible function call optimizations. |
778 class CallOptimization BASE_EMBEDDED { | 715 class CallOptimization BASE_EMBEDDED { |
779 public: | 716 public: |
780 explicit CallOptimization(LookupResult* lookup); | 717 explicit CallOptimization(LookupResult* lookup); |
781 | 718 |
782 explicit CallOptimization(Handle<JSFunction> function); | 719 explicit CallOptimization(Handle<JSFunction> function); |
783 | 720 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 Handle<JSFunction> constant_function_; | 764 Handle<JSFunction> constant_function_; |
828 bool is_simple_api_call_; | 765 bool is_simple_api_call_; |
829 Handle<FunctionTemplateInfo> expected_receiver_type_; | 766 Handle<FunctionTemplateInfo> expected_receiver_type_; |
830 Handle<CallHandlerInfo> api_call_info_; | 767 Handle<CallHandlerInfo> api_call_info_; |
831 }; | 768 }; |
832 | 769 |
833 | 770 |
834 } } // namespace v8::internal | 771 } } // namespace v8::internal |
835 | 772 |
836 #endif // V8_STUB_CACHE_H_ | 773 #endif // V8_STUB_CACHE_H_ |
OLD | NEW |