| OLD | NEW | 
|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 423 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 434     code = compiler.CompileStoreField(receiver, field_index, transition, name); | 434     code = compiler.CompileStoreField(receiver, field_index, transition, name); | 
| 435     if (code->IsFailure()) return code; | 435     if (code->IsFailure()) return code; | 
| 436     PROFILE(CodeCreateEvent( | 436     PROFILE(CodeCreateEvent( | 
| 437         Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); | 437         Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); | 
| 438     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 438     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 
| 439     if (result->IsFailure()) return result; | 439     if (result->IsFailure()) return result; | 
| 440   } | 440   } | 
| 441   return code; | 441   return code; | 
| 442 } | 442 } | 
| 443 | 443 | 
|  | 444 #define CALL_LOGGER_TAG(kind, type) \ | 
|  | 445     (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 
| 444 | 446 | 
| 445 Object* StubCache::ComputeCallConstant(int argc, | 447 Object* StubCache::ComputeCallConstant(int argc, | 
| 446                                        InLoopFlag in_loop, | 448                                        InLoopFlag in_loop, | 
|  | 449                                        Code::Kind kind, | 
| 447                                        String* name, | 450                                        String* name, | 
| 448                                        Object* object, | 451                                        Object* object, | 
| 449                                        JSObject* holder, | 452                                        JSObject* holder, | 
| 450                                        JSFunction* function) { | 453                                        JSFunction* function) { | 
| 451   // Compute the check type and the map. | 454   // Compute the check type and the map. | 
| 452   Map* map = IC::GetCodeCacheMapForObject(object); | 455   Map* map = IC::GetCodeCacheMapForObject(object); | 
| 453 | 456 | 
| 454   // Compute check type based on receiver/holder. | 457   // Compute check type based on receiver/holder. | 
| 455   StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; | 458   StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; | 
| 456   if (object->IsString()) { | 459   if (object->IsString()) { | 
| 457     check = StubCompiler::STRING_CHECK; | 460     check = StubCompiler::STRING_CHECK; | 
| 458   } else if (object->IsNumber()) { | 461   } else if (object->IsNumber()) { | 
| 459     check = StubCompiler::NUMBER_CHECK; | 462     check = StubCompiler::NUMBER_CHECK; | 
| 460   } else if (object->IsBoolean()) { | 463   } else if (object->IsBoolean()) { | 
| 461     check = StubCompiler::BOOLEAN_CHECK; | 464     check = StubCompiler::BOOLEAN_CHECK; | 
| 462   } | 465   } | 
| 463 | 466 | 
| 464   Code::Flags flags = | 467   Code::Flags flags = | 
| 465       Code::ComputeMonomorphicFlags(Code::CALL_IC, | 468       Code::ComputeMonomorphicFlags(kind, | 
| 466                                     CONSTANT_FUNCTION, | 469                                     CONSTANT_FUNCTION, | 
| 467                                     in_loop, | 470                                     in_loop, | 
| 468                                     argc); | 471                                     argc); | 
| 469   Object* code = map->FindInCodeCache(name, flags); | 472   Object* code = map->FindInCodeCache(name, flags); | 
| 470   if (code->IsUndefined()) { | 473   if (code->IsUndefined()) { | 
| 471     // If the function hasn't been compiled yet, we cannot do it now | 474     // If the function hasn't been compiled yet, we cannot do it now | 
| 472     // because it may cause GC. To avoid this issue, we return an | 475     // because it may cause GC. To avoid this issue, we return an | 
| 473     // internal error which will make sure we do not update any | 476     // internal error which will make sure we do not update any | 
| 474     // caches. | 477     // caches. | 
| 475     if (!function->is_compiled()) return Failure::InternalError(); | 478     if (!function->is_compiled()) return Failure::InternalError(); | 
| 476     // Compile the stub - only create stubs for fully compiled functions. | 479     // Compile the stub - only create stubs for fully compiled functions. | 
| 477     CallStubCompiler compiler(argc, in_loop); | 480     CallStubCompiler compiler(argc, in_loop, kind); | 
| 478     code = compiler.CompileCallConstant(object, holder, function, name, check); | 481     code = compiler.CompileCallConstant(object, holder, function, name, check); | 
| 479     if (code->IsFailure()) return code; | 482     if (code->IsFailure()) return code; | 
| 480     ASSERT_EQ(flags, Code::cast(code)->flags()); | 483     ASSERT_EQ(flags, Code::cast(code)->flags()); | 
| 481     PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 484     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 
|  | 485                             Code::cast(code), name)); | 
| 482     Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 486     Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 
| 483     if (result->IsFailure()) return result; | 487     if (result->IsFailure()) return result; | 
| 484   } | 488   } | 
| 485   return Set(name, map, Code::cast(code)); | 489   return Set(name, map, Code::cast(code)); | 
| 486 } | 490 } | 
| 487 | 491 | 
| 488 | 492 | 
| 489 Object* StubCache::ComputeCallField(int argc, | 493 Object* StubCache::ComputeCallField(int argc, | 
| 490                                     InLoopFlag in_loop, | 494                                     InLoopFlag in_loop, | 
|  | 495                                     Code::Kind kind, | 
| 491                                     String* name, | 496                                     String* name, | 
| 492                                     Object* object, | 497                                     Object* object, | 
| 493                                     JSObject* holder, | 498                                     JSObject* holder, | 
| 494                                     int index) { | 499                                     int index) { | 
| 495   // Compute the check type and the map. | 500   // Compute the check type and the map. | 
| 496   Map* map = IC::GetCodeCacheMapForObject(object); | 501   Map* map = IC::GetCodeCacheMapForObject(object); | 
| 497 | 502 | 
| 498   // TODO(1233596): We cannot do receiver map check for non-JS objects | 503   // TODO(1233596): We cannot do receiver map check for non-JS objects | 
| 499   // because they may be represented as immediates without a | 504   // because they may be represented as immediates without a | 
| 500   // map. Instead, we check against the map in the holder. | 505   // map. Instead, we check against the map in the holder. | 
| 501   if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 506   if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 
| 502     object = holder; | 507     object = holder; | 
| 503   } | 508   } | 
| 504 | 509 | 
| 505   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 510   Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 
| 506                                                     FIELD, | 511                                                     FIELD, | 
| 507                                                     in_loop, | 512                                                     in_loop, | 
| 508                                                     argc); | 513                                                     argc); | 
| 509   Object* code = map->FindInCodeCache(name, flags); | 514   Object* code = map->FindInCodeCache(name, flags); | 
| 510   if (code->IsUndefined()) { | 515   if (code->IsUndefined()) { | 
| 511     CallStubCompiler compiler(argc, in_loop); | 516     CallStubCompiler compiler(argc, in_loop, kind); | 
| 512     code = compiler.CompileCallField(JSObject::cast(object), | 517     code = compiler.CompileCallField(JSObject::cast(object), | 
| 513                                      holder, | 518                                      holder, | 
| 514                                      index, | 519                                      index, | 
| 515                                      name); | 520                                      name); | 
| 516     if (code->IsFailure()) return code; | 521     if (code->IsFailure()) return code; | 
| 517     ASSERT_EQ(flags, Code::cast(code)->flags()); | 522     ASSERT_EQ(flags, Code::cast(code)->flags()); | 
| 518     PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 523     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 
|  | 524                             Code::cast(code), name)); | 
| 519     Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 525     Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 
| 520     if (result->IsFailure()) return result; | 526     if (result->IsFailure()) return result; | 
| 521   } | 527   } | 
| 522   return Set(name, map, Code::cast(code)); | 528   return Set(name, map, Code::cast(code)); | 
| 523 } | 529 } | 
| 524 | 530 | 
| 525 | 531 | 
| 526 Object* StubCache::ComputeCallInterceptor(int argc, | 532 Object* StubCache::ComputeCallInterceptor(int argc, | 
|  | 533                                           Code::Kind kind, | 
| 527                                           String* name, | 534                                           String* name, | 
| 528                                           Object* object, | 535                                           Object* object, | 
| 529                                           JSObject* holder) { | 536                                           JSObject* holder) { | 
| 530   // Compute the check type and the map. | 537   // Compute the check type and the map. | 
| 531   // If the object is a value, we use the prototype map for the cache. | 538   // If the object is a value, we use the prototype map for the cache. | 
| 532   Map* map = IC::GetCodeCacheMapForObject(object); | 539   Map* map = IC::GetCodeCacheMapForObject(object); | 
| 533 | 540 | 
| 534   // TODO(1233596): We cannot do receiver map check for non-JS objects | 541   // TODO(1233596): We cannot do receiver map check for non-JS objects | 
| 535   // because they may be represented as immediates without a | 542   // because they may be represented as immediates without a | 
| 536   // map. Instead, we check against the map in the holder. | 543   // map. Instead, we check against the map in the holder. | 
| 537   if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 544   if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 
| 538     object = holder; | 545     object = holder; | 
| 539   } | 546   } | 
| 540 | 547 | 
| 541   Code::Flags flags = | 548   Code::Flags flags = | 
| 542       Code::ComputeMonomorphicFlags(Code::CALL_IC, | 549       Code::ComputeMonomorphicFlags(kind, | 
| 543                                     INTERCEPTOR, | 550                                     INTERCEPTOR, | 
| 544                                     NOT_IN_LOOP, | 551                                     NOT_IN_LOOP, | 
| 545                                     argc); | 552                                     argc); | 
| 546   Object* code = map->FindInCodeCache(name, flags); | 553   Object* code = map->FindInCodeCache(name, flags); | 
| 547   if (code->IsUndefined()) { | 554   if (code->IsUndefined()) { | 
| 548     CallStubCompiler compiler(argc, NOT_IN_LOOP); | 555     CallStubCompiler compiler(argc, NOT_IN_LOOP, kind); | 
| 549     code = compiler.CompileCallInterceptor(JSObject::cast(object), | 556     code = compiler.CompileCallInterceptor(JSObject::cast(object), | 
| 550                                            holder, | 557                                            holder, | 
| 551                                            name); | 558                                            name); | 
| 552     if (code->IsFailure()) return code; | 559     if (code->IsFailure()) return code; | 
| 553     ASSERT_EQ(flags, Code::cast(code)->flags()); | 560     ASSERT_EQ(flags, Code::cast(code)->flags()); | 
| 554     PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 561     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 
|  | 562                             Code::cast(code), name)); | 
| 555     Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 563     Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 
| 556     if (result->IsFailure()) return result; | 564     if (result->IsFailure()) return result; | 
| 557   } | 565   } | 
| 558   return Set(name, map, Code::cast(code)); | 566   return Set(name, map, Code::cast(code)); | 
| 559 } | 567 } | 
| 560 | 568 | 
| 561 | 569 | 
| 562 Object* StubCache::ComputeCallNormal(int argc, | 570 Object* StubCache::ComputeCallNormal(int argc, | 
| 563                                      InLoopFlag in_loop, | 571                                      InLoopFlag in_loop, | 
|  | 572                                      Code::Kind kind, | 
| 564                                      String* name, | 573                                      String* name, | 
| 565                                      JSObject* receiver) { | 574                                      JSObject* receiver) { | 
| 566   Object* code = ComputeCallNormal(argc, in_loop); | 575   Object* code = ComputeCallNormal(argc, in_loop, kind); | 
| 567   if (code->IsFailure()) return code; | 576   if (code->IsFailure()) return code; | 
| 568   return Set(name, receiver->map(), Code::cast(code)); | 577   return Set(name, receiver->map(), Code::cast(code)); | 
| 569 } | 578 } | 
| 570 | 579 | 
| 571 | 580 | 
| 572 Object* StubCache::ComputeCallGlobal(int argc, | 581 Object* StubCache::ComputeCallGlobal(int argc, | 
| 573                                      InLoopFlag in_loop, | 582                                      InLoopFlag in_loop, | 
|  | 583                                      Code::Kind kind, | 
| 574                                      String* name, | 584                                      String* name, | 
| 575                                      JSObject* receiver, | 585                                      JSObject* receiver, | 
| 576                                      GlobalObject* holder, | 586                                      GlobalObject* holder, | 
| 577                                      JSGlobalPropertyCell* cell, | 587                                      JSGlobalPropertyCell* cell, | 
| 578                                      JSFunction* function) { | 588                                      JSFunction* function) { | 
| 579   Code::Flags flags = | 589   Code::Flags flags = | 
| 580       Code::ComputeMonomorphicFlags(Code::CALL_IC, NORMAL, in_loop, argc); | 590       Code::ComputeMonomorphicFlags(kind, | 
|  | 591                                     NORMAL, | 
|  | 592                                     in_loop, | 
|  | 593                                     argc); | 
| 581   Object* code = receiver->map()->FindInCodeCache(name, flags); | 594   Object* code = receiver->map()->FindInCodeCache(name, flags); | 
| 582   if (code->IsUndefined()) { | 595   if (code->IsUndefined()) { | 
| 583     // If the function hasn't been compiled yet, we cannot do it now | 596     // If the function hasn't been compiled yet, we cannot do it now | 
| 584     // because it may cause GC. To avoid this issue, we return an | 597     // because it may cause GC. To avoid this issue, we return an | 
| 585     // internal error which will make sure we do not update any | 598     // internal error which will make sure we do not update any | 
| 586     // caches. | 599     // caches. | 
| 587     if (!function->is_compiled()) return Failure::InternalError(); | 600     if (!function->is_compiled()) return Failure::InternalError(); | 
| 588     CallStubCompiler compiler(argc, in_loop); | 601     CallStubCompiler compiler(argc, in_loop, kind); | 
| 589     code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 602     code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 
| 590     if (code->IsFailure()) return code; | 603     if (code->IsFailure()) return code; | 
| 591     ASSERT_EQ(flags, Code::cast(code)->flags()); | 604     ASSERT_EQ(flags, Code::cast(code)->flags()); | 
| 592     PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 605     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 
|  | 606                             Code::cast(code), name)); | 
| 593     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 607     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 
| 594     if (result->IsFailure()) return result; | 608     if (result->IsFailure()) return result; | 
| 595   } | 609   } | 
| 596   return Set(name, receiver->map(), Code::cast(code)); | 610   return Set(name, receiver->map(), Code::cast(code)); | 
| 597 } | 611 } | 
| 598 | 612 | 
| 599 | 613 | 
| 600 static Object* GetProbeValue(Code::Flags flags) { | 614 static Object* GetProbeValue(Code::Flags flags) { | 
| 601   // Use raw_unchecked... so we don't get assert failures during GC. | 615   // Use raw_unchecked... so we don't get assert failures during GC. | 
| 602   NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); | 616   NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 630     ASSERT(entry != -1); | 644     ASSERT(entry != -1); | 
| 631     ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == | 645     ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == | 
| 632            Heap::undefined_value()); | 646            Heap::undefined_value()); | 
| 633     Heap::non_monomorphic_cache()->ValueAtPut(entry, code); | 647     Heap::non_monomorphic_cache()->ValueAtPut(entry, code); | 
| 634     CHECK(GetProbeValue(Code::cast(code)->flags()) == code); | 648     CHECK(GetProbeValue(Code::cast(code)->flags()) == code); | 
| 635   } | 649   } | 
| 636   return code; | 650   return code; | 
| 637 } | 651 } | 
| 638 | 652 | 
| 639 | 653 | 
| 640 Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) { | 654 Code* StubCache::FindCallInitialize(int argc, | 
|  | 655                                     InLoopFlag in_loop, | 
|  | 656                                     Code::Kind kind) { | 
| 641   Code::Flags flags = | 657   Code::Flags flags = | 
| 642       Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc); | 658       Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); | 
| 643   Object* result = ProbeCache(flags); | 659   Object* result = ProbeCache(flags); | 
| 644   ASSERT(!result->IsUndefined()); | 660   ASSERT(!result->IsUndefined()); | 
| 645   // This might be called during the marking phase of the collector | 661   // This might be called during the marking phase of the collector | 
| 646   // hence the unchecked cast. | 662   // hence the unchecked cast. | 
| 647   return reinterpret_cast<Code*>(result); | 663   return reinterpret_cast<Code*>(result); | 
| 648 } | 664 } | 
| 649 | 665 | 
| 650 | 666 | 
| 651 Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) { | 667 Object* StubCache::ComputeCallInitialize(int argc, | 
|  | 668                                          InLoopFlag in_loop, | 
|  | 669                                          Code::Kind kind) { | 
| 652   Code::Flags flags = | 670   Code::Flags flags = | 
| 653       Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc); | 671       Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); | 
| 654   Object* probe = ProbeCache(flags); | 672   Object* probe = ProbeCache(flags); | 
| 655   if (!probe->IsUndefined()) return probe; | 673   if (!probe->IsUndefined()) return probe; | 
| 656   StubCompiler compiler; | 674   StubCompiler compiler; | 
| 657   return FillCache(compiler.CompileCallInitialize(flags)); | 675   return FillCache(compiler.CompileCallInitialize(flags)); | 
| 658 } | 676 } | 
| 659 | 677 | 
| 660 | 678 | 
| 661 Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop) { | 679 Object* StubCache::ComputeCallPreMonomorphic(int argc, | 
|  | 680                                              InLoopFlag in_loop, | 
|  | 681                                              Code::Kind kind) { | 
| 662   Code::Flags flags = | 682   Code::Flags flags = | 
| 663       Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL, argc); | 683       Code::ComputeFlags(kind, in_loop, PREMONOMORPHIC, NORMAL, argc); | 
| 664   Object* probe = ProbeCache(flags); | 684   Object* probe = ProbeCache(flags); | 
| 665   if (!probe->IsUndefined()) return probe; | 685   if (!probe->IsUndefined()) return probe; | 
| 666   StubCompiler compiler; | 686   StubCompiler compiler; | 
| 667   return FillCache(compiler.CompileCallPreMonomorphic(flags)); | 687   return FillCache(compiler.CompileCallPreMonomorphic(flags)); | 
| 668 } | 688 } | 
| 669 | 689 | 
| 670 | 690 | 
| 671 Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) { | 691 Object* StubCache::ComputeCallNormal(int argc, | 
|  | 692                                      InLoopFlag in_loop, | 
|  | 693                                      Code::Kind kind) { | 
| 672   Code::Flags flags = | 694   Code::Flags flags = | 
| 673       Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL, argc); | 695       Code::ComputeFlags(kind, in_loop, MONOMORPHIC, NORMAL, argc); | 
| 674   Object* probe = ProbeCache(flags); | 696   Object* probe = ProbeCache(flags); | 
| 675   if (!probe->IsUndefined()) return probe; | 697   if (!probe->IsUndefined()) return probe; | 
| 676   StubCompiler compiler; | 698   StubCompiler compiler; | 
| 677   return FillCache(compiler.CompileCallNormal(flags)); | 699   return FillCache(compiler.CompileCallNormal(flags)); | 
| 678 } | 700 } | 
| 679 | 701 | 
| 680 | 702 | 
| 681 Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) { | 703 Object* StubCache::ComputeCallMegamorphic(int argc, | 
|  | 704                                           InLoopFlag in_loop, | 
|  | 705                                           Code::Kind kind) { | 
| 682   Code::Flags flags = | 706   Code::Flags flags = | 
| 683       Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL, argc); | 707       Code::ComputeFlags(kind, in_loop, MEGAMORPHIC, NORMAL, argc); | 
| 684   Object* probe = ProbeCache(flags); | 708   Object* probe = ProbeCache(flags); | 
| 685   if (!probe->IsUndefined()) return probe; | 709   if (!probe->IsUndefined()) return probe; | 
| 686   StubCompiler compiler; | 710   StubCompiler compiler; | 
| 687   return FillCache(compiler.CompileCallMegamorphic(flags)); | 711   return FillCache(compiler.CompileCallMegamorphic(flags)); | 
| 688 } | 712 } | 
| 689 | 713 | 
| 690 | 714 | 
| 691 Object* StubCache::ComputeCallMiss(int argc) { | 715 Object* StubCache::ComputeCallMiss(int argc, Code::Kind kind) { | 
| 692   Code::Flags flags = | 716   // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs | 
| 693       Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL, argc); | 717   // and monomorphic stubs are not mixed up together in the stub cache. | 
|  | 718   Code::Flags flags = Code::ComputeFlags( | 
|  | 719      kind, NOT_IN_LOOP, MONOMORPHIC_PROTOTYPE_FAILURE, NORMAL, argc); | 
| 694   Object* probe = ProbeCache(flags); | 720   Object* probe = ProbeCache(flags); | 
| 695   if (!probe->IsUndefined()) return probe; | 721   if (!probe->IsUndefined()) return probe; | 
| 696   StubCompiler compiler; | 722   StubCompiler compiler; | 
| 697   return FillCache(compiler.CompileCallMiss(flags)); | 723   return FillCache(compiler.CompileCallMiss(flags)); | 
| 698 } | 724 } | 
| 699 | 725 | 
| 700 | 726 | 
| 701 #ifdef ENABLE_DEBUGGER_SUPPORT | 727 #ifdef ENABLE_DEBUGGER_SUPPORT | 
| 702 Object* StubCache::ComputeCallDebugBreak(int argc) { | 728 Object* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) { | 
| 703   Code::Flags flags = | 729   Code::Flags flags = | 
| 704       Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); | 730       Code::ComputeFlags(kind, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); | 
| 705   Object* probe = ProbeCache(flags); | 731   Object* probe = ProbeCache(flags); | 
| 706   if (!probe->IsUndefined()) return probe; | 732   if (!probe->IsUndefined()) return probe; | 
| 707   StubCompiler compiler; | 733   StubCompiler compiler; | 
| 708   return FillCache(compiler.CompileCallDebugBreak(flags)); | 734   return FillCache(compiler.CompileCallDebugBreak(flags)); | 
| 709 } | 735 } | 
| 710 | 736 | 
| 711 | 737 | 
| 712 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) { | 738 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { | 
| 713   Code::Flags flags = | 739   Code::Flags flags = | 
| 714       Code::ComputeFlags(Code::CALL_IC, | 740       Code::ComputeFlags(kind, | 
| 715                          NOT_IN_LOOP, | 741                          NOT_IN_LOOP, | 
| 716                          DEBUG_PREPARE_STEP_IN, | 742                          DEBUG_PREPARE_STEP_IN, | 
| 717                          NORMAL, | 743                          NORMAL, | 
| 718                          argc); | 744                          argc); | 
| 719   Object* probe = ProbeCache(flags); | 745   Object* probe = ProbeCache(flags); | 
| 720   if (!probe->IsUndefined()) return probe; | 746   if (!probe->IsUndefined()) return probe; | 
| 721   StubCompiler compiler; | 747   StubCompiler compiler; | 
| 722   return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); | 748   return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); | 
| 723 } | 749 } | 
| 724 #endif | 750 #endif | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 751     secondary_[j].value = Builtins::builtin(Builtins::Illegal); | 777     secondary_[j].value = Builtins::builtin(Builtins::Illegal); | 
| 752   } | 778   } | 
| 753 } | 779 } | 
| 754 | 780 | 
| 755 | 781 | 
| 756 // ------------------------------------------------------------------------ | 782 // ------------------------------------------------------------------------ | 
| 757 // StubCompiler implementation. | 783 // StubCompiler implementation. | 
| 758 | 784 | 
| 759 | 785 | 
| 760 // Support function for computing call IC miss stubs. | 786 // Support function for computing call IC miss stubs. | 
| 761 Handle<Code> ComputeCallMiss(int argc) { | 787 Handle<Code> ComputeCallMiss(int argc, Code::Kind kind) { | 
| 762   CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code); | 788   CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc, kind), Code); | 
| 763 } | 789 } | 
| 764 | 790 | 
| 765 | 791 | 
| 766 | 792 | 
| 767 Object* LoadCallbackProperty(Arguments args) { | 793 Object* LoadCallbackProperty(Arguments args) { | 
| 768   ASSERT(args[0]->IsJSObject()); | 794   ASSERT(args[0]->IsJSObject()); | 
| 769   ASSERT(args[1]->IsJSObject()); | 795   ASSERT(args[1]->IsJSObject()); | 
| 770   AccessorInfo* callback = AccessorInfo::cast(args[2]); | 796   AccessorInfo* callback = AccessorInfo::cast(args[2]); | 
| 771   Address getter_address = v8::ToCData<Address>(callback->getter()); | 797   Address getter_address = v8::ToCData<Address>(callback->getter()); | 
| 772   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); | 798   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); | 
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 959 Object* KeyedLoadPropertyWithInterceptor(Arguments args) { | 985 Object* KeyedLoadPropertyWithInterceptor(Arguments args) { | 
| 960   JSObject* receiver = JSObject::cast(args[0]); | 986   JSObject* receiver = JSObject::cast(args[0]); | 
| 961   uint32_t index = Smi::cast(args[1])->value(); | 987   uint32_t index = Smi::cast(args[1])->value(); | 
| 962   return receiver->GetElementWithInterceptor(receiver, index); | 988   return receiver->GetElementWithInterceptor(receiver, index); | 
| 963 } | 989 } | 
| 964 | 990 | 
| 965 | 991 | 
| 966 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { | 992 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { | 
| 967   HandleScope scope; | 993   HandleScope scope; | 
| 968   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 994   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 
| 969   CallIC::GenerateInitialize(masm(), argc); | 995   Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 996   if (kind == Code::CALL_IC) { | 
|  | 997     CallIC::GenerateInitialize(masm(), argc); | 
|  | 998   } else { | 
|  | 999     KeyedCallIC::GenerateInitialize(masm(), argc); | 
|  | 1000   } | 
| 970   Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); | 1001   Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); | 
| 971   if (!result->IsFailure()) { | 1002   if (!result->IsFailure()) { | 
| 972     Counters::call_initialize_stubs.Increment(); | 1003     Counters::call_initialize_stubs.Increment(); | 
| 973     Code* code = Code::cast(result); | 1004     Code* code = Code::cast(result); | 
| 974     USE(code); | 1005     USE(code); | 
| 975     PROFILE(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG, | 1006     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), | 
| 976                             code, code->arguments_count())); | 1007                             code, code->arguments_count())); | 
| 977   } | 1008   } | 
| 978   return result; | 1009   return result; | 
| 979 } | 1010 } | 
| 980 | 1011 | 
| 981 | 1012 | 
| 982 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | 1013 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | 
| 983   HandleScope scope; | 1014   HandleScope scope; | 
| 984   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1015   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 
| 985   // The code of the PreMonomorphic stub is the same as the code | 1016   // The code of the PreMonomorphic stub is the same as the code | 
| 986   // of the Initialized stub.  They just differ on the code object flags. | 1017   // of the Initialized stub.  They just differ on the code object flags. | 
| 987   CallIC::GenerateInitialize(masm(), argc); | 1018   Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 1019   if (kind == Code::CALL_IC) { | 
|  | 1020     CallIC::GenerateInitialize(masm(), argc); | 
|  | 1021   } else { | 
|  | 1022     KeyedCallIC::GenerateInitialize(masm(), argc); | 
|  | 1023   } | 
| 988   Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | 1024   Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | 
| 989   if (!result->IsFailure()) { | 1025   if (!result->IsFailure()) { | 
| 990     Counters::call_premonomorphic_stubs.Increment(); | 1026     Counters::call_premonomorphic_stubs.Increment(); | 
| 991     Code* code = Code::cast(result); | 1027     Code* code = Code::cast(result); | 
| 992     USE(code); | 1028     USE(code); | 
| 993     PROFILE(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG, | 1029     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), | 
| 994                             code, code->arguments_count())); | 1030                             code, code->arguments_count())); | 
| 995   } | 1031   } | 
| 996   return result; | 1032   return result; | 
| 997 } | 1033 } | 
| 998 | 1034 | 
| 999 | 1035 | 
| 1000 Object* StubCompiler::CompileCallNormal(Code::Flags flags) { | 1036 Object* StubCompiler::CompileCallNormal(Code::Flags flags) { | 
| 1001   HandleScope scope; | 1037   HandleScope scope; | 
| 1002   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1038   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 
| 1003   CallIC::GenerateNormal(masm(), argc); | 1039   Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 1040   if (kind == Code::CALL_IC) { | 
|  | 1041     CallIC::GenerateNormal(masm(), argc); | 
|  | 1042   } else { | 
|  | 1043     KeyedCallIC::GenerateNormal(masm(), argc); | 
|  | 1044   } | 
| 1004   Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); | 1045   Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); | 
| 1005   if (!result->IsFailure()) { | 1046   if (!result->IsFailure()) { | 
| 1006     Counters::call_normal_stubs.Increment(); | 1047     Counters::call_normal_stubs.Increment(); | 
| 1007     Code* code = Code::cast(result); | 1048     Code* code = Code::cast(result); | 
| 1008     USE(code); | 1049     USE(code); | 
| 1009     PROFILE(CodeCreateEvent(Logger::CALL_NORMAL_TAG, | 1050     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), | 
| 1010                             code, code->arguments_count())); | 1051                             code, code->arguments_count())); | 
| 1011   } | 1052   } | 
| 1012   return result; | 1053   return result; | 
| 1013 } | 1054 } | 
| 1014 | 1055 | 
| 1015 | 1056 | 
| 1016 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | 1057 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | 
| 1017   HandleScope scope; | 1058   HandleScope scope; | 
| 1018   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1059   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 
| 1019   CallIC::GenerateMegamorphic(masm(), argc); | 1060   Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 1061   if (kind == Code::CALL_IC) { | 
|  | 1062     CallIC::GenerateMegamorphic(masm(), argc); | 
|  | 1063   } else { | 
|  | 1064     KeyedCallIC::GenerateMegamorphic(masm(), argc); | 
|  | 1065   } | 
|  | 1066 | 
| 1020   Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); | 1067   Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); | 
| 1021   if (!result->IsFailure()) { | 1068   if (!result->IsFailure()) { | 
| 1022     Counters::call_megamorphic_stubs.Increment(); | 1069     Counters::call_megamorphic_stubs.Increment(); | 
| 1023     Code* code = Code::cast(result); | 1070     Code* code = Code::cast(result); | 
| 1024     USE(code); | 1071     USE(code); | 
| 1025     PROFILE(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG, | 1072     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), | 
| 1026                             code, code->arguments_count())); | 1073                             code, code->arguments_count())); | 
| 1027   } | 1074   } | 
| 1028   return result; | 1075   return result; | 
| 1029 } | 1076 } | 
| 1030 | 1077 | 
| 1031 | 1078 | 
| 1032 Object* StubCompiler::CompileCallMiss(Code::Flags flags) { | 1079 Object* StubCompiler::CompileCallMiss(Code::Flags flags) { | 
| 1033   HandleScope scope; | 1080   HandleScope scope; | 
| 1034   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1081   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 
| 1035   CallIC::GenerateMiss(masm(), argc); | 1082   Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 1083   if (kind == Code::CALL_IC) { | 
|  | 1084     CallIC::GenerateMiss(masm(), argc); | 
|  | 1085   } else { | 
|  | 1086     KeyedCallIC::GenerateMiss(masm(), argc); | 
|  | 1087   } | 
| 1036   Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); | 1088   Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); | 
| 1037   if (!result->IsFailure()) { | 1089   if (!result->IsFailure()) { | 
| 1038     Counters::call_megamorphic_stubs.Increment(); | 1090     Counters::call_megamorphic_stubs.Increment(); | 
| 1039     Code* code = Code::cast(result); | 1091     Code* code = Code::cast(result); | 
| 1040     USE(code); | 1092     USE(code); | 
| 1041     PROFILE(CodeCreateEvent(Logger::CALL_MISS_TAG, | 1093     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), | 
| 1042                             code, code->arguments_count())); | 1094                             code, code->arguments_count())); | 
| 1043   } | 1095   } | 
| 1044   return result; | 1096   return result; | 
| 1045 } | 1097 } | 
| 1046 | 1098 | 
| 1047 | 1099 | 
| 1048 #ifdef ENABLE_DEBUGGER_SUPPORT | 1100 #ifdef ENABLE_DEBUGGER_SUPPORT | 
| 1049 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | 1101 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | 
| 1050   HandleScope scope; | 1102   HandleScope scope; | 
| 1051   Debug::GenerateCallICDebugBreak(masm()); | 1103   Debug::GenerateCallICDebugBreak(masm()); | 
| 1052   Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | 1104   Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | 
| 1053   if (!result->IsFailure()) { | 1105   if (!result->IsFailure()) { | 
| 1054     Code* code = Code::cast(result); | 1106     Code* code = Code::cast(result); | 
| 1055     USE(code); | 1107     USE(code); | 
| 1056     PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG, | 1108     Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 1109     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG), | 
| 1057                             code, code->arguments_count())); | 1110                             code, code->arguments_count())); | 
| 1058   } | 1111   } | 
| 1059   return result; | 1112   return result; | 
| 1060 } | 1113 } | 
| 1061 | 1114 | 
| 1062 | 1115 | 
| 1063 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | 1116 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | 
| 1064   HandleScope scope; | 1117   HandleScope scope; | 
| 1065   // Use the same code for the the step in preparations as we do for | 1118   // Use the same code for the the step in preparations as we do for | 
| 1066   // the miss case. | 1119   // the miss case. | 
| 1067   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1120   int argc = Code::ExtractArgumentsCountFromFlags(flags); | 
| 1068   CallIC::GenerateMiss(masm(), argc); | 1121   Code::Kind kind = Code::ExtractKindFromFlags(flags); | 
|  | 1122   if (kind == Code::CALL_IC) { | 
|  | 1123     CallIC::GenerateMiss(masm(), argc); | 
|  | 1124   } else { | 
|  | 1125     KeyedCallIC::GenerateMiss(masm(), argc); | 
|  | 1126   } | 
| 1069   Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | 1127   Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | 
| 1070   if (!result->IsFailure()) { | 1128   if (!result->IsFailure()) { | 
| 1071     Code* code = Code::cast(result); | 1129     Code* code = Code::cast(result); | 
| 1072     USE(code); | 1130     USE(code); | 
| 1073     PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG, | 1131     PROFILE(CodeCreateEvent( | 
| 1074                             code, code->arguments_count())); | 1132         CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), | 
|  | 1133         code, | 
|  | 1134         code->arguments_count())); | 
| 1075   } | 1135   } | 
| 1076   return result; | 1136   return result; | 
| 1077 } | 1137 } | 
| 1078 #endif | 1138 #endif | 
| 1079 | 1139 | 
|  | 1140 #undef CALL_LOGGER_TAG | 
| 1080 | 1141 | 
| 1081 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { | 1142 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { | 
| 1082   // Check for allocation failures during stub compilation. | 1143   // Check for allocation failures during stub compilation. | 
| 1083   if (failure_->IsFailure()) return failure_; | 1144   if (failure_->IsFailure()) return failure_; | 
| 1084 | 1145 | 
| 1085   // Create code object in the heap. | 1146   // Create code object in the heap. | 
| 1086   CodeDesc desc; | 1147   CodeDesc desc; | 
| 1087   masm_.GetCode(&desc); | 1148   masm_.GetCode(&desc); | 
| 1088   Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); | 1149   Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); | 
| 1089 #ifdef ENABLE_DISASSEMBLER | 1150 #ifdef ENABLE_DISASSEMBLER | 
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1160       CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1221       CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 
| 1161 #undef CALL_GENERATOR_CASE | 1222 #undef CALL_GENERATOR_CASE | 
| 1162     } | 1223     } | 
| 1163     UNREACHABLE(); | 1224     UNREACHABLE(); | 
| 1164     return Heap::undefined_value(); | 1225     return Heap::undefined_value(); | 
| 1165 } | 1226 } | 
| 1166 | 1227 | 
| 1167 | 1228 | 
| 1168 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { | 1229 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { | 
| 1169   int argc = arguments_.immediate(); | 1230   int argc = arguments_.immediate(); | 
| 1170   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 1231   Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, | 
| 1171                                                     type, | 1232                                                     type, | 
| 1172                                                     in_loop_, | 1233                                                     in_loop_, | 
| 1173                                                     argc); | 1234                                                     argc); | 
| 1174   return GetCodeWithFlags(flags, name); | 1235   return GetCodeWithFlags(flags, name); | 
| 1175 } | 1236 } | 
| 1176 | 1237 | 
| 1177 | 1238 | 
| 1178 Object* CallStubCompiler::GetCode(JSFunction* function) { | 1239 Object* CallStubCompiler::GetCode(JSFunction* function) { | 
| 1179   String* function_name = NULL; | 1240   String* function_name = NULL; | 
| 1180   if (function->shared()->name()->IsString()) { | 1241   if (function->shared()->name()->IsString()) { | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1257       expected_receiver_type_ = | 1318       expected_receiver_type_ = | 
| 1258           FunctionTemplateInfo::cast(signature->receiver()); | 1319           FunctionTemplateInfo::cast(signature->receiver()); | 
| 1259     } | 1320     } | 
| 1260   } | 1321   } | 
| 1261 | 1322 | 
| 1262   is_simple_api_call_ = true; | 1323   is_simple_api_call_ = true; | 
| 1263 } | 1324 } | 
| 1264 | 1325 | 
| 1265 | 1326 | 
| 1266 } }  // namespace v8::internal | 1327 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|