Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 &done, | 142 &done, |
| 143 receiver, | 143 receiver, |
| 144 properties, | 144 properties, |
| 145 name, | 145 name, |
| 146 scratch1); | 146 scratch1); |
| 147 __ bind(&done); | 147 __ bind(&done); |
| 148 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 148 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 149 } | 149 } |
| 150 | 150 |
| 151 | 151 |
| 152 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 153 // handlified. | |
| 154 MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( | |
| 155 MacroAssembler* masm, | |
| 156 Label* miss_label, | |
| 157 Register receiver, | |
| 158 String* name, | |
| 159 Register scratch0, | |
| 160 Register scratch1) { | |
| 161 ASSERT(name->IsSymbol()); | |
| 162 Counters* counters = masm->isolate()->counters(); | |
| 163 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | |
| 164 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | |
| 165 | |
| 166 Label done; | |
| 167 | |
| 168 const int kInterceptorOrAccessCheckNeededMask = | |
| 169 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | |
| 170 | |
| 171 // Bail out if the receiver has a named interceptor or requires access checks. | |
| 172 Register map = scratch1; | |
| 173 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
| 174 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | |
| 175 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | |
| 176 __ b(ne, miss_label); | |
| 177 | |
| 178 // Check that receiver is a JSObject. | |
| 179 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
| 180 __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
| 181 __ b(lt, miss_label); | |
| 182 | |
| 183 // Load properties array. | |
| 184 Register properties = scratch0; | |
| 185 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 186 // Check that the properties array is a dictionary. | |
| 187 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | |
| 188 Register tmp = properties; | |
| 189 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | |
| 190 __ cmp(map, tmp); | |
| 191 __ b(ne, miss_label); | |
| 192 | |
| 193 // Restore the temporarily used register. | |
| 194 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 195 | |
| 196 | |
| 197 MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( | |
| 198 masm, | |
| 199 miss_label, | |
| 200 &done, | |
| 201 receiver, | |
| 202 properties, | |
| 203 name, | |
| 204 scratch1); | |
| 205 if (result->IsFailure()) return result; | |
| 206 | |
| 207 __ bind(&done); | |
| 208 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | |
| 209 | |
| 210 return result; | |
| 211 } | |
| 212 | |
| 213 | |
| 214 void StubCache::GenerateProbe(MacroAssembler* masm, | 152 void StubCache::GenerateProbe(MacroAssembler* masm, |
| 215 Code::Flags flags, | 153 Code::Flags flags, |
| 216 Register receiver, | 154 Register receiver, |
| 217 Register name, | 155 Register name, |
| 218 Register scratch, | 156 Register scratch, |
| 219 Register extra, | 157 Register extra, |
| 220 Register extra2) { | 158 Register extra2) { |
| 221 Isolate* isolate = masm->isolate(); | 159 Isolate* isolate = masm->isolate(); |
| 222 Label miss; | 160 Label miss; |
| 223 | 161 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); | 225 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); |
| 288 // Load the initial map. The global functions all have initial maps. | 226 // Load the initial map. The global functions all have initial maps. |
| 289 __ ldr(prototype, | 227 __ ldr(prototype, |
| 290 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | 228 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); |
| 291 // Load the prototype from the initial map. | 229 // Load the prototype from the initial map. |
| 292 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 230 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 293 } | 231 } |
| 294 | 232 |
| 295 | 233 |
| 296 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 234 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 297 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 235 MacroAssembler* masm, |
| 236 int index, | |
| 237 Register prototype, | |
| 238 Label* miss) { | |
| 298 Isolate* isolate = masm->isolate(); | 239 Isolate* isolate = masm->isolate(); |
| 299 // Check we're still in the same context. | 240 // Check we're still in the same context. |
| 300 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 241 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 301 __ Move(ip, isolate->global()); | 242 __ Move(ip, isolate->global()); |
| 302 __ cmp(prototype, ip); | 243 __ cmp(prototype, ip); |
| 303 __ b(ne, miss); | 244 __ b(ne, miss); |
| 304 // Get the global function with the given index. | 245 // Get the global function with the given index. |
| 305 JSFunction* function = | 246 Handle<JSFunction> function( |
| 306 JSFunction::cast(isolate->global_context()->get(index)); | 247 JSFunction::cast(isolate->global_context()->get(index))); |
| 307 // Load its initial map. The global functions all have initial maps. | 248 // Load its initial map. The global functions all have initial maps. |
| 308 __ Move(prototype, Handle<Map>(function->initial_map())); | 249 __ Move(prototype, Handle<Map>(function->initial_map())); |
| 309 // Load the prototype from the initial map. | 250 // Load the prototype from the initial map. |
| 310 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 251 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 311 } | 252 } |
| 312 | 253 |
| 313 | 254 |
| 314 // Load a fast property out of a holder object (src). In-object properties | 255 // Load a fast property out of a holder object (src). In-object properties |
| 315 // are loaded directly otherwise the property is loaded from the properties | 256 // are loaded directly otherwise the property is loaded from the properties |
| 316 // fixed array. | 257 // fixed array. |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 ? CALL_AS_FUNCTION | 500 ? CALL_AS_FUNCTION |
| 560 : CALL_AS_METHOD; | 501 : CALL_AS_METHOD; |
| 561 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 502 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 562 } | 503 } |
| 563 | 504 |
| 564 | 505 |
| 565 static void PushInterceptorArguments(MacroAssembler* masm, | 506 static void PushInterceptorArguments(MacroAssembler* masm, |
| 566 Register receiver, | 507 Register receiver, |
| 567 Register holder, | 508 Register holder, |
| 568 Register name, | 509 Register name, |
| 569 JSObject* holder_obj) { | 510 Handle<JSObject> holder_obj) { |
| 570 __ push(name); | 511 __ push(name); |
| 571 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 512 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 572 ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor)); | 513 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 573 Register scratch = name; | 514 Register scratch = name; |
| 574 __ mov(scratch, Operand(Handle<Object>(interceptor))); | 515 __ mov(scratch, Operand(interceptor)); |
| 575 __ push(scratch); | 516 __ push(scratch); |
| 576 __ push(receiver); | 517 __ push(receiver); |
| 577 __ push(holder); | 518 __ push(holder); |
| 578 __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); | 519 __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); |
| 579 __ push(scratch); | 520 __ push(scratch); |
| 580 } | 521 } |
| 581 | 522 |
| 582 | 523 |
| 583 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 524 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
| 584 Register receiver, | 525 Register receiver, |
| 585 Register holder, | 526 Register holder, |
| 586 Register name, | 527 Register name, |
| 587 JSObject* holder_obj) { | 528 Handle<JSObject> holder_obj) { |
| 588 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 529 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 589 | 530 |
| 590 ExternalReference ref = | 531 ExternalReference ref = |
| 591 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 532 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
| 592 masm->isolate()); | 533 masm->isolate()); |
| 593 __ mov(r0, Operand(5)); | 534 __ mov(r0, Operand(5)); |
| 594 __ mov(r1, Operand(ref)); | 535 __ mov(r1, Operand(ref)); |
| 595 | 536 |
| 596 CEntryStub stub(1); | 537 CEntryStub stub(1); |
| 597 __ CallStub(&stub); | 538 __ CallStub(&stub); |
| 598 } | 539 } |
| 599 | 540 |
| 541 | |
| 600 static const int kFastApiCallArguments = 3; | 542 static const int kFastApiCallArguments = 3; |
| 601 | 543 |
| 602 // Reserves space for the extra arguments to FastHandleApiCall in the | 544 // Reserves space for the extra arguments to FastHandleApiCall in the |
| 603 // caller's frame. | 545 // caller's frame. |
| 604 // | 546 // |
| 605 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. | 547 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
| 606 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 548 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
| 607 Register scratch) { | 549 Register scratch) { |
| 608 __ mov(scratch, Operand(Smi::FromInt(0))); | 550 __ mov(scratch, Operand(Smi::FromInt(0))); |
| 609 for (int i = 0; i < kFastApiCallArguments; i++) { | 551 for (int i = 0; i < kFastApiCallArguments; i++) { |
| 610 __ push(scratch); | 552 __ push(scratch); |
| 611 } | 553 } |
| 612 } | 554 } |
| 613 | 555 |
| 614 | 556 |
| 615 // Undoes the effects of ReserveSpaceForFastApiCall. | 557 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 616 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 558 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
| 617 __ Drop(kFastApiCallArguments); | 559 __ Drop(kFastApiCallArguments); |
| 618 } | 560 } |
| 619 | 561 |
| 620 | 562 |
| 621 static MaybeObject* GenerateFastApiDirectCall( | 563 static void GenerateFastApiDirectCall(MacroAssembler* masm, |
| 622 MacroAssembler* masm, | 564 const CallOptimization& optimization, |
| 623 const CallOptimization& optimization, | 565 int argc) { |
| 624 int argc) { | |
| 625 // ----------- S t a t e ------------- | 566 // ----------- S t a t e ------------- |
| 626 // -- sp[0] : holder (set by CheckPrototypes) | 567 // -- sp[0] : holder (set by CheckPrototypes) |
| 627 // -- sp[4] : callee js function | 568 // -- sp[4] : callee js function |
| 628 // -- sp[8] : call data | 569 // -- sp[8] : call data |
| 629 // -- sp[12] : last js argument | 570 // -- sp[12] : last js argument |
| 630 // -- ... | 571 // -- ... |
| 631 // -- sp[(argc + 3) * 4] : first js argument | 572 // -- sp[(argc + 3) * 4] : first js argument |
| 632 // -- sp[(argc + 4) * 4] : receiver | 573 // -- sp[(argc + 4) * 4] : receiver |
| 633 // ----------------------------------- | 574 // ----------------------------------- |
| 634 // Get the function and setup the context. | 575 // Get the function and setup the context. |
| 635 JSFunction* function = optimization.constant_function(); | 576 Handle<JSFunction> function = optimization.constant_function(); |
| 636 __ mov(r5, Operand(Handle<JSFunction>(function))); | 577 __ mov(r5, Operand(function)); |
| 637 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); | 578 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); |
| 638 | 579 |
| 639 // Pass the additional arguments FastHandleApiCall expects. | 580 // Pass the additional arguments FastHandleApiCall expects. |
| 640 Object* call_data = optimization.api_call_info()->data(); | 581 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 641 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 582 Handle<Object> call_data(api_call_info->data()); |
| 642 if (masm->isolate()->heap()->InNewSpace(call_data)) { | 583 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
| 643 __ Move(r0, api_call_info_handle); | 584 __ Move(r0, api_call_info); |
| 644 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); | 585 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
| 645 } else { | 586 } else { |
| 646 __ Move(r6, Handle<Object>(call_data)); | 587 __ Move(r6, call_data); |
| 647 } | 588 } |
| 648 // Store js function and call data. | 589 // Store js function and call data. |
| 649 __ stm(ib, sp, r5.bit() | r6.bit()); | 590 __ stm(ib, sp, r5.bit() | r6.bit()); |
| 650 | 591 |
| 651 // r2 points to call data as expected by Arguments | 592 // r2 points to call data as expected by Arguments |
| 652 // (refer to layout above). | 593 // (refer to layout above). |
| 653 __ add(r2, sp, Operand(2 * kPointerSize)); | 594 __ add(r2, sp, Operand(2 * kPointerSize)); |
| 654 | 595 |
| 655 Object* callback = optimization.api_call_info()->callback(); | |
| 656 Address api_function_address = v8::ToCData<Address>(callback); | |
| 657 ApiFunction fun(api_function_address); | |
| 658 | |
| 659 const int kApiStackSpace = 4; | 596 const int kApiStackSpace = 4; |
| 660 | 597 |
| 661 FrameScope frame_scope(masm, StackFrame::MANUAL); | 598 FrameScope frame_scope(masm, StackFrame::MANUAL); |
| 662 __ EnterExitFrame(false, kApiStackSpace); | 599 __ EnterExitFrame(false, kApiStackSpace); |
| 663 | 600 |
| 664 // r0 = v8::Arguments& | 601 // r0 = v8::Arguments& |
| 665 // Arguments is after the return address. | 602 // Arguments is after the return address. |
| 666 __ add(r0, sp, Operand(1 * kPointerSize)); | 603 __ add(r0, sp, Operand(1 * kPointerSize)); |
| 667 // v8::Arguments::implicit_args = data | 604 // v8::Arguments::implicit_args = data |
| 668 __ str(r2, MemOperand(r0, 0 * kPointerSize)); | 605 __ str(r2, MemOperand(r0, 0 * kPointerSize)); |
| 669 // v8::Arguments::values = last argument | 606 // v8::Arguments::values = last argument |
| 670 __ add(ip, r2, Operand(argc * kPointerSize)); | 607 __ add(ip, r2, Operand(argc * kPointerSize)); |
| 671 __ str(ip, MemOperand(r0, 1 * kPointerSize)); | 608 __ str(ip, MemOperand(r0, 1 * kPointerSize)); |
| 672 // v8::Arguments::length_ = argc | 609 // v8::Arguments::length_ = argc |
| 673 __ mov(ip, Operand(argc)); | 610 __ mov(ip, Operand(argc)); |
| 674 __ str(ip, MemOperand(r0, 2 * kPointerSize)); | 611 __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
| 675 // v8::Arguments::is_construct_call = 0 | 612 // v8::Arguments::is_construct_call = 0 |
| 676 __ mov(ip, Operand(0)); | 613 __ mov(ip, Operand(0)); |
| 677 __ str(ip, MemOperand(r0, 3 * kPointerSize)); | 614 __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
| 678 | 615 |
| 679 // Emitting a stub call may try to allocate (if the code is not | |
| 680 // already generated). Do not allow the assembler to perform a | |
| 681 // garbage collection but instead return the allocation failure | |
| 682 // object. | |
| 683 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; | 616 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; |
| 617 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | |
| 618 ApiFunction fun(function_address); | |
| 684 ExternalReference ref = ExternalReference(&fun, | 619 ExternalReference ref = ExternalReference(&fun, |
| 685 ExternalReference::DIRECT_API_CALL, | 620 ExternalReference::DIRECT_API_CALL, |
| 686 masm->isolate()); | 621 masm->isolate()); |
| 687 AllowExternalCallThatCantCauseGC scope(masm); | 622 AllowExternalCallThatCantCauseGC scope(masm); |
| 688 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 623 |
| 624 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); | |
| 689 } | 625 } |
| 690 | 626 |
| 691 | 627 |
| 692 class CallInterceptorCompiler BASE_EMBEDDED { | 628 class CallInterceptorCompiler BASE_EMBEDDED { |
| 693 public: | 629 public: |
| 694 CallInterceptorCompiler(StubCompiler* stub_compiler, | 630 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 695 const ParameterCount& arguments, | 631 const ParameterCount& arguments, |
| 696 Register name, | 632 Register name, |
| 697 Code::ExtraICState extra_ic_state) | 633 Code::ExtraICState extra_ic_state) |
| 698 : stub_compiler_(stub_compiler), | 634 : stub_compiler_(stub_compiler), |
| 699 arguments_(arguments), | 635 arguments_(arguments), |
| 700 name_(name), | 636 name_(name), |
| 701 extra_ic_state_(extra_ic_state) {} | 637 extra_ic_state_(extra_ic_state) {} |
| 702 | 638 |
| 703 MaybeObject* Compile(MacroAssembler* masm, | 639 void Compile(MacroAssembler* masm, |
| 704 JSObject* object, | 640 Handle<JSObject> object, |
| 705 JSObject* holder, | 641 Handle<JSObject> holder, |
| 706 String* name, | 642 Handle<String> name, |
| 707 LookupResult* lookup, | 643 LookupResult* lookup, |
| 708 Register receiver, | 644 Register receiver, |
| 709 Register scratch1, | 645 Register scratch1, |
| 710 Register scratch2, | 646 Register scratch2, |
| 711 Register scratch3, | 647 Register scratch3, |
| 712 Label* miss) { | 648 Label* miss) { |
| 713 ASSERT(holder->HasNamedInterceptor()); | 649 ASSERT(holder->HasNamedInterceptor()); |
| 714 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 650 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 715 | 651 |
| 716 // Check that the receiver isn't a smi. | 652 // Check that the receiver isn't a smi. |
| 717 __ JumpIfSmi(receiver, miss); | 653 __ JumpIfSmi(receiver, miss); |
| 718 | |
| 719 CallOptimization optimization(lookup); | 654 CallOptimization optimization(lookup); |
| 720 | |
| 721 if (optimization.is_constant_call()) { | 655 if (optimization.is_constant_call()) { |
| 722 return CompileCacheable(masm, | 656 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, |
| 723 object, | 657 holder, lookup, name, optimization, miss); |
| 724 receiver, | |
| 725 scratch1, | |
| 726 scratch2, | |
| 727 scratch3, | |
| 728 holder, | |
| 729 lookup, | |
| 730 name, | |
| 731 optimization, | |
| 732 miss); | |
| 733 } else { | 658 } else { |
| 734 CompileRegular(masm, | 659 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, |
| 735 object, | 660 name, holder, miss); |
| 736 receiver, | |
| 737 scratch1, | |
| 738 scratch2, | |
| 739 scratch3, | |
| 740 name, | |
| 741 holder, | |
| 742 miss); | |
| 743 return masm->isolate()->heap()->undefined_value(); | |
| 744 } | 661 } |
| 745 } | 662 } |
| 746 | 663 |
| 747 private: | 664 private: |
| 748 MaybeObject* CompileCacheable(MacroAssembler* masm, | 665 void CompileCacheable(MacroAssembler* masm, |
| 749 JSObject* object, | 666 Handle<JSObject> object, |
| 750 Register receiver, | 667 Register receiver, |
| 751 Register scratch1, | 668 Register scratch1, |
| 752 Register scratch2, | 669 Register scratch2, |
| 753 Register scratch3, | 670 Register scratch3, |
| 754 JSObject* interceptor_holder, | 671 Handle<JSObject> interceptor_holder, |
| 755 LookupResult* lookup, | 672 LookupResult* lookup, |
| 756 String* name, | 673 Handle<String> name, |
| 757 const CallOptimization& optimization, | 674 const CallOptimization& optimization, |
| 758 Label* miss_label) { | 675 Label* miss_label) { |
| 759 ASSERT(optimization.is_constant_call()); | 676 ASSERT(optimization.is_constant_call()); |
| 760 ASSERT(!lookup->holder()->IsGlobalObject()); | 677 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 761 | |
| 762 Counters* counters = masm->isolate()->counters(); | 678 Counters* counters = masm->isolate()->counters(); |
| 763 | |
| 764 int depth1 = kInvalidProtoDepth; | 679 int depth1 = kInvalidProtoDepth; |
| 765 int depth2 = kInvalidProtoDepth; | 680 int depth2 = kInvalidProtoDepth; |
| 766 bool can_do_fast_api_call = false; | 681 bool can_do_fast_api_call = false; |
| 767 if (optimization.is_simple_api_call() && | 682 if (optimization.is_simple_api_call() && |
| 768 !lookup->holder()->IsGlobalObject()) { | 683 !lookup->holder()->IsGlobalObject()) { |
| 769 depth1 = | 684 depth1 = optimization.GetPrototypeDepthOfExpectedType( |
| 770 optimization.GetPrototypeDepthOfExpectedType(object, | 685 object, interceptor_holder); |
| 771 interceptor_holder); | 686 if (depth1 == kInvalidProtoDepth) { |
| 772 if (depth1 == kInvalidProtoDepth) { | 687 depth2 = optimization.GetPrototypeDepthOfExpectedType( |
| 773 depth2 = | 688 interceptor_holder, Handle<JSObject>(lookup->holder())); |
| 774 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 689 } |
| 775 lookup->holder()); | 690 can_do_fast_api_call = |
| 776 } | 691 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; |
| 777 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | |
| 778 (depth2 != kInvalidProtoDepth); | |
| 779 } | 692 } |
| 780 | 693 |
| 781 __ IncrementCounter(counters->call_const_interceptor(), 1, | 694 __ IncrementCounter(counters->call_const_interceptor(), 1, |
| 782 scratch1, scratch2); | 695 scratch1, scratch2); |
| 783 | 696 |
| 784 if (can_do_fast_api_call) { | 697 if (can_do_fast_api_call) { |
| 785 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, | 698 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, |
| 786 scratch1, scratch2); | 699 scratch1, scratch2); |
| 787 ReserveSpaceForFastApiCall(masm, scratch1); | 700 ReserveSpaceForFastApiCall(masm, scratch1); |
| 788 } | 701 } |
| 789 | 702 |
| 790 // Check that the maps from receiver to interceptor's holder | 703 // Check that the maps from receiver to interceptor's holder |
| 791 // haven't changed and thus we can invoke interceptor. | 704 // haven't changed and thus we can invoke interceptor. |
| 792 Label miss_cleanup; | 705 Label miss_cleanup; |
| 793 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 706 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 794 Register holder = | 707 Register holder = |
| 795 stub_compiler_->CheckPrototypes(object, receiver, | 708 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 796 interceptor_holder, scratch1, | 709 scratch1, scratch2, scratch3, |
| 797 scratch2, scratch3, name, depth1, miss); | 710 name, depth1, miss); |
| 798 | 711 |
| 799 // Invoke an interceptor and if it provides a value, | 712 // Invoke an interceptor and if it provides a value, |
| 800 // branch to |regular_invoke|. | 713 // branch to |regular_invoke|. |
| 801 Label regular_invoke; | 714 Label regular_invoke; |
| 802 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 715 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
| 803 ®ular_invoke); | 716 ®ular_invoke); |
| 804 | 717 |
| 805 // Interceptor returned nothing for this property. Try to use cached | 718 // Interceptor returned nothing for this property. Try to use cached |
| 806 // constant function. | 719 // constant function. |
| 807 | 720 |
| 808 // Check that the maps from interceptor's holder to constant function's | 721 // Check that the maps from interceptor's holder to constant function's |
| 809 // holder haven't changed and thus we can use cached constant function. | 722 // holder haven't changed and thus we can use cached constant function. |
| 810 if (interceptor_holder != lookup->holder()) { | 723 if (*interceptor_holder != lookup->holder()) { |
| 811 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 724 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
| 812 lookup->holder(), scratch1, | 725 Handle<JSObject>(lookup->holder()), |
| 813 scratch2, scratch3, name, depth2, miss); | 726 scratch1, scratch2, scratch3, |
| 727 name, depth2, miss); | |
| 814 } else { | 728 } else { |
| 815 // CheckPrototypes has a side effect of fetching a 'holder' | 729 // CheckPrototypes has a side effect of fetching a 'holder' |
| 816 // for API (object which is instanceof for the signature). It's | 730 // for API (object which is instanceof for the signature). It's |
| 817 // safe to omit it here, as if present, it should be fetched | 731 // safe to omit it here, as if present, it should be fetched |
| 818 // by the previous CheckPrototypes. | 732 // by the previous CheckPrototypes. |
| 819 ASSERT(depth2 == kInvalidProtoDepth); | 733 ASSERT(depth2 == kInvalidProtoDepth); |
| 820 } | 734 } |
| 821 | 735 |
| 822 // Invoke function. | 736 // Invoke function. |
| 823 if (can_do_fast_api_call) { | 737 if (can_do_fast_api_call) { |
| 824 MaybeObject* result = GenerateFastApiDirectCall(masm, | 738 GenerateFastApiDirectCall(masm, optimization, arguments_.immediate()); |
| 825 optimization, | |
| 826 arguments_.immediate()); | |
| 827 if (result->IsFailure()) return result; | |
| 828 } else { | 739 } else { |
| 829 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 740 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 830 ? CALL_AS_FUNCTION | 741 ? CALL_AS_FUNCTION |
| 831 : CALL_AS_METHOD; | 742 : CALL_AS_METHOD; |
| 832 __ InvokeFunction(optimization.constant_function(), arguments_, | 743 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 833 JUMP_FUNCTION, call_kind); | 744 JUMP_FUNCTION, call_kind); |
| 834 } | 745 } |
| 835 | 746 |
| 836 // Deferred code for fast API call case---clean preallocated space. | 747 // Deferred code for fast API call case---clean preallocated space. |
| 837 if (can_do_fast_api_call) { | 748 if (can_do_fast_api_call) { |
| 838 __ bind(&miss_cleanup); | 749 __ bind(&miss_cleanup); |
| 839 FreeSpaceForFastApiCall(masm); | 750 FreeSpaceForFastApiCall(masm); |
| 840 __ b(miss_label); | 751 __ b(miss_label); |
| 841 } | 752 } |
| 842 | 753 |
| 843 // Invoke a regular function. | 754 // Invoke a regular function. |
| 844 __ bind(®ular_invoke); | 755 __ bind(®ular_invoke); |
| 845 if (can_do_fast_api_call) { | 756 if (can_do_fast_api_call) { |
| 846 FreeSpaceForFastApiCall(masm); | 757 FreeSpaceForFastApiCall(masm); |
| 847 } | 758 } |
| 848 | |
| 849 return masm->isolate()->heap()->undefined_value(); | |
| 850 } | 759 } |
| 851 | 760 |
| 852 void CompileRegular(MacroAssembler* masm, | 761 void CompileRegular(MacroAssembler* masm, |
| 853 JSObject* object, | 762 Handle<JSObject> object, |
| 854 Register receiver, | 763 Register receiver, |
| 855 Register scratch1, | 764 Register scratch1, |
| 856 Register scratch2, | 765 Register scratch2, |
| 857 Register scratch3, | 766 Register scratch3, |
| 858 String* name, | 767 Handle<String> name, |
| 859 JSObject* interceptor_holder, | 768 Handle<JSObject> interceptor_holder, |
| 860 Label* miss_label) { | 769 Label* miss_label) { |
| 861 Register holder = | 770 Register holder = |
| 862 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 771 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 863 scratch1, scratch2, scratch3, name, | 772 scratch1, scratch2, scratch3, |
| 864 miss_label); | 773 name, miss_label); |
| 865 | 774 |
| 866 // Call a runtime function to load the interceptor property. | 775 // Call a runtime function to load the interceptor property. |
| 867 FrameScope scope(masm, StackFrame::INTERNAL); | 776 FrameScope scope(masm, StackFrame::INTERNAL); |
| 868 // Save the name_ register across the call. | 777 // Save the name_ register across the call. |
| 869 __ push(name_); | 778 __ push(name_); |
| 870 | 779 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 871 PushInterceptorArguments(masm, | |
| 872 receiver, | |
| 873 holder, | |
| 874 name_, | |
| 875 interceptor_holder); | |
| 876 | |
| 877 __ CallExternalReference( | 780 __ CallExternalReference( |
| 878 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 781 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 879 masm->isolate()), | 782 masm->isolate()), |
| 880 5); | 783 5); |
| 881 | |
| 882 // Restore the name_ register. | 784 // Restore the name_ register. |
| 883 __ pop(name_); | 785 __ pop(name_); |
| 884 | |
| 885 // Leave the internal frame. | 786 // Leave the internal frame. |
| 886 } | 787 } |
| 887 | 788 |
| 888 void LoadWithInterceptor(MacroAssembler* masm, | 789 void LoadWithInterceptor(MacroAssembler* masm, |
| 889 Register receiver, | 790 Register receiver, |
| 890 Register holder, | 791 Register holder, |
| 891 JSObject* holder_obj, | 792 Handle<JSObject> holder_obj, |
| 892 Register scratch, | 793 Register scratch, |
| 893 Label* interceptor_succeeded) { | 794 Label* interceptor_succeeded) { |
| 894 { | 795 { |
| 895 FrameScope scope(masm, StackFrame::INTERNAL); | 796 FrameScope scope(masm, StackFrame::INTERNAL); |
| 896 __ Push(holder, name_); | 797 __ Push(holder, name_); |
| 897 | |
| 898 CompileCallLoadPropertyWithInterceptor(masm, | 798 CompileCallLoadPropertyWithInterceptor(masm, |
| 899 receiver, | 799 receiver, |
| 900 holder, | 800 holder, |
| 901 name_, | 801 name_, |
| 902 holder_obj); | 802 holder_obj); |
| 903 | |
| 904 __ pop(name_); // Restore the name. | 803 __ pop(name_); // Restore the name. |
| 905 __ pop(receiver); // Restore the holder. | 804 __ pop(receiver); // Restore the holder. |
| 906 } | 805 } |
| 907 | |
| 908 // If interceptor returns no-result sentinel, call the constant function. | 806 // If interceptor returns no-result sentinel, call the constant function. |
| 909 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 807 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 910 __ cmp(r0, scratch); | 808 __ cmp(r0, scratch); |
| 911 __ b(ne, interceptor_succeeded); | 809 __ b(ne, interceptor_succeeded); |
| 912 } | 810 } |
| 913 | 811 |
| 914 StubCompiler* stub_compiler_; | 812 StubCompiler* stub_compiler_; |
| 915 const ParameterCount& arguments_; | 813 const ParameterCount& arguments_; |
| 916 Register name_; | 814 Register name_; |
| 917 Code::ExtraICState extra_ic_state_; | 815 Code::ExtraICState extra_ic_state_; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 931 ASSERT(cell->value()->IsTheHole()); | 829 ASSERT(cell->value()->IsTheHole()); |
| 932 __ mov(scratch, Operand(cell)); | 830 __ mov(scratch, Operand(cell)); |
| 933 __ ldr(scratch, | 831 __ ldr(scratch, |
| 934 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 832 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
| 935 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 833 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 936 __ cmp(scratch, ip); | 834 __ cmp(scratch, ip); |
| 937 __ b(ne, miss); | 835 __ b(ne, miss); |
| 938 } | 836 } |
| 939 | 837 |
| 940 | 838 |
| 941 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 942 // handlified. | |
| 943 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( | |
| 944 MacroAssembler* masm, | |
| 945 GlobalObject* global, | |
| 946 String* name, | |
| 947 Register scratch, | |
| 948 Label* miss) { | |
| 949 Object* probe; | |
| 950 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | |
| 951 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | |
| 952 } | |
| 953 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | |
| 954 ASSERT(cell->value()->IsTheHole()); | |
| 955 __ mov(scratch, Operand(Handle<Object>(cell))); | |
| 956 __ ldr(scratch, | |
| 957 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | |
| 958 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
| 959 __ cmp(scratch, ip); | |
| 960 __ b(ne, miss); | |
| 961 return cell; | |
| 962 } | |
| 963 | |
| 964 | |
| 965 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 839 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 966 // from object to (but not including) holder. | 840 // from object to (but not including) holder. |
| 967 static void GenerateCheckPropertyCells(MacroAssembler* masm, | 841 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 968 Handle<JSObject> object, | 842 Handle<JSObject> object, |
| 969 Handle<JSObject> holder, | 843 Handle<JSObject> holder, |
| 970 Handle<String> name, | 844 Handle<String> name, |
| 971 Register scratch, | 845 Register scratch, |
| 972 Label* miss) { | 846 Label* miss) { |
| 973 Handle<JSObject> current = object; | 847 Handle<JSObject> current = object; |
| 974 while (!current.is_identical_to(holder)) { | 848 while (!current.is_identical_to(holder)) { |
| 975 if (current->IsGlobalObject()) { | 849 if (current->IsGlobalObject()) { |
| 976 GenerateCheckPropertyCell(masm, | 850 GenerateCheckPropertyCell(masm, |
| 977 Handle<GlobalObject>::cast(current), | 851 Handle<GlobalObject>::cast(current), |
| 978 name, | 852 name, |
| 979 scratch, | 853 scratch, |
| 980 miss); | 854 miss); |
| 981 } | 855 } |
| 982 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 856 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 983 } | 857 } |
| 984 } | 858 } |
| 985 | 859 |
| 986 | 860 |
| 987 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 988 // handlified. | |
| 989 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( | |
| 990 MacroAssembler* masm, | |
| 991 JSObject* object, | |
| 992 JSObject* holder, | |
| 993 String* name, | |
| 994 Register scratch, | |
| 995 Label* miss) { | |
| 996 JSObject* current = object; | |
| 997 while (current != holder) { | |
| 998 if (current->IsGlobalObject()) { | |
| 999 // Returns a cell or a failure. | |
| 1000 MaybeObject* result = TryGenerateCheckPropertyCell( | |
| 1001 masm, | |
| 1002 GlobalObject::cast(current), | |
| 1003 name, | |
| 1004 scratch, | |
| 1005 miss); | |
| 1006 if (result->IsFailure()) return result; | |
| 1007 } | |
| 1008 ASSERT(current->IsJSObject()); | |
| 1009 current = JSObject::cast(current->GetPrototype()); | |
| 1010 } | |
| 1011 return NULL; | |
| 1012 } | |
| 1013 | |
| 1014 | |
| 1015 // Convert and store int passed in register ival to IEEE 754 single precision | 861 // Convert and store int passed in register ival to IEEE 754 single precision |
| 1016 // floating point value at memory location (dst + 4 * wordoffset) | 862 // floating point value at memory location (dst + 4 * wordoffset) |
| 1017 // If VFP3 is available use it for conversion. | 863 // If VFP3 is available use it for conversion. |
| 1018 static void StoreIntAsFloat(MacroAssembler* masm, | 864 static void StoreIntAsFloat(MacroAssembler* masm, |
| 1019 Register dst, | 865 Register dst, |
| 1020 Register wordoffset, | 866 Register wordoffset, |
| 1021 Register ival, | 867 Register ival, |
| 1022 Register fval, | 868 Register fval, |
| 1023 Register scratch1, | 869 Register scratch1, |
| 1024 Register scratch2) { | 870 Register scratch2) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1219 // If we've skipped any global objects, it's not enough to verify that | 1065 // If we've skipped any global objects, it's not enough to verify that |
| 1220 // their maps haven't changed. We also need to check that the property | 1066 // their maps haven't changed. We also need to check that the property |
| 1221 // cell for the property is still empty. | 1067 // cell for the property is still empty. |
| 1222 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1068 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1223 | 1069 |
| 1224 // Return the register containing the holder. | 1070 // Return the register containing the holder. |
| 1225 return reg; | 1071 return reg; |
| 1226 } | 1072 } |
| 1227 | 1073 |
| 1228 | 1074 |
| 1229 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 1230 // handlified. | |
| 1231 Register StubCompiler::CheckPrototypes(JSObject* object, | |
| 1232 Register object_reg, | |
| 1233 JSObject* holder, | |
| 1234 Register holder_reg, | |
| 1235 Register scratch1, | |
| 1236 Register scratch2, | |
| 1237 String* name, | |
| 1238 int save_at_depth, | |
| 1239 Label* miss) { | |
| 1240 // Make sure there's no overlap between holder and object registers. | |
| 1241 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | |
| 1242 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | |
| 1243 && !scratch2.is(scratch1)); | |
| 1244 | |
| 1245 // Keep track of the current object in register reg. | |
| 1246 Register reg = object_reg; | |
| 1247 int depth = 0; | |
| 1248 | |
| 1249 if (save_at_depth == depth) { | |
| 1250 __ str(reg, MemOperand(sp)); | |
| 1251 } | |
| 1252 | |
| 1253 // Check the maps in the prototype chain. | |
| 1254 // Traverse the prototype chain from the object and do map checks. | |
| 1255 JSObject* current = object; | |
| 1256 while (current != holder) { | |
| 1257 depth++; | |
| 1258 | |
| 1259 // Only global objects and objects that do not require access | |
| 1260 // checks are allowed in stubs. | |
| 1261 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
| 1262 | |
| 1263 ASSERT(current->GetPrototype()->IsJSObject()); | |
| 1264 JSObject* prototype = JSObject::cast(current->GetPrototype()); | |
| 1265 if (!current->HasFastProperties() && | |
| 1266 !current->IsJSGlobalObject() && | |
| 1267 !current->IsJSGlobalProxy()) { | |
| 1268 if (!name->IsSymbol()) { | |
| 1269 MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name); | |
| 1270 Object* lookup_result = NULL; // Initialization to please compiler. | |
| 1271 if (!maybe_lookup_result->ToObject(&lookup_result)) { | |
| 1272 set_failure(Failure::cast(maybe_lookup_result)); | |
| 1273 return reg; | |
| 1274 } | |
| 1275 name = String::cast(lookup_result); | |
| 1276 } | |
| 1277 ASSERT(current->property_dictionary()->FindEntry(name) == | |
| 1278 StringDictionary::kNotFound); | |
| 1279 | |
| 1280 MaybeObject* negative_lookup = | |
| 1281 TryGenerateDictionaryNegativeLookup(masm(), | |
| 1282 miss, | |
| 1283 reg, | |
| 1284 name, | |
| 1285 scratch1, | |
| 1286 scratch2); | |
| 1287 if (negative_lookup->IsFailure()) { | |
| 1288 set_failure(Failure::cast(negative_lookup)); | |
| 1289 return reg; | |
| 1290 } | |
| 1291 | |
| 1292 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1293 reg = holder_reg; // from now the object is in holder_reg | |
| 1294 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
| 1295 } else if (heap()->InNewSpace(prototype)) { | |
| 1296 // Get the map of the current object. | |
| 1297 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1298 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | |
| 1299 | |
| 1300 // Branch on the result of the map check. | |
| 1301 __ b(ne, miss); | |
| 1302 | |
| 1303 // Check access rights to the global object. This has to happen | |
| 1304 // after the map check so that we know that the object is | |
| 1305 // actually a global object. | |
| 1306 if (current->IsJSGlobalProxy()) { | |
| 1307 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1308 // Restore scratch register to be the map of the object. In the | |
| 1309 // new space case below, we load the prototype from the map in | |
| 1310 // the scratch register. | |
| 1311 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1312 } | |
| 1313 | |
| 1314 reg = holder_reg; // from now the object is in holder_reg | |
| 1315 // The prototype is in new space; we cannot store a reference | |
| 1316 // to it in the code. Load it from the map. | |
| 1317 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
| 1318 } else { | |
| 1319 // Check the map of the current object. | |
| 1320 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1321 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | |
| 1322 // Branch on the result of the map check. | |
| 1323 __ b(ne, miss); | |
| 1324 // Check access rights to the global object. This has to happen | |
| 1325 // after the map check so that we know that the object is | |
| 1326 // actually a global object. | |
| 1327 if (current->IsJSGlobalProxy()) { | |
| 1328 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1329 } | |
| 1330 // The prototype is in old space; load it directly. | |
| 1331 reg = holder_reg; // from now the object is in holder_reg | |
| 1332 __ mov(reg, Operand(Handle<JSObject>(prototype))); | |
| 1333 } | |
| 1334 | |
| 1335 if (save_at_depth == depth) { | |
| 1336 __ str(reg, MemOperand(sp)); | |
| 1337 } | |
| 1338 | |
| 1339 // Go to the next object in the prototype chain. | |
| 1340 current = prototype; | |
| 1341 } | |
| 1342 | |
| 1343 // Check the holder map. | |
| 1344 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1345 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | |
| 1346 __ b(ne, miss); | |
| 1347 | |
| 1348 // Log the check depth. | |
| 1349 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); | |
| 1350 | |
| 1351 // Perform security check for access to the global object. | |
| 1352 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
| 1353 if (holder->IsJSGlobalProxy()) { | |
| 1354 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1355 } | |
| 1356 | |
| 1357 // If we've skipped any global objects, it's not enough to verify | |
| 1358 // that their maps haven't changed. We also need to check that the | |
| 1359 // property cell for the property is still empty. | |
| 1360 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), | |
| 1361 object, | |
| 1362 holder, | |
| 1363 name, | |
| 1364 scratch1, | |
| 1365 miss); | |
| 1366 if (result->IsFailure()) set_failure(Failure::cast(result)); | |
| 1367 | |
| 1368 // Return the register containing the holder. | |
| 1369 return reg; | |
| 1370 } | |
| 1371 | |
| 1372 | |
| 1373 void StubCompiler::GenerateLoadField(Handle<JSObject> object, | 1075 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
| 1374 Handle<JSObject> holder, | 1076 Handle<JSObject> holder, |
| 1375 Register receiver, | 1077 Register receiver, |
| 1376 Register scratch1, | 1078 Register scratch1, |
| 1377 Register scratch2, | 1079 Register scratch2, |
| 1378 Register scratch3, | 1080 Register scratch3, |
| 1379 int index, | 1081 int index, |
| 1380 Handle<String> name, | 1082 Handle<String> name, |
| 1381 Label* miss) { | 1083 Label* miss) { |
| 1382 // Check that the receiver isn't a smi. | 1084 // Check that the receiver isn't a smi. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1405 // Check that the maps haven't changed. | 1107 // Check that the maps haven't changed. |
| 1406 CheckPrototypes( | 1108 CheckPrototypes( |
| 1407 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 1109 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1408 | 1110 |
| 1409 // Return the constant value. | 1111 // Return the constant value. |
| 1410 __ mov(r0, Operand(value)); | 1112 __ mov(r0, Operand(value)); |
| 1411 __ Ret(); | 1113 __ Ret(); |
| 1412 } | 1114 } |
| 1413 | 1115 |
| 1414 | 1116 |
| 1415 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1117 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
| 1416 JSObject* holder, | 1118 Handle<JSObject> holder, |
| 1417 Register receiver, | 1119 Register receiver, |
| 1418 Register name_reg, | 1120 Register name_reg, |
| 1419 Register scratch1, | 1121 Register scratch1, |
| 1420 Register scratch2, | 1122 Register scratch2, |
| 1421 Register scratch3, | 1123 Register scratch3, |
| 1422 AccessorInfo* callback, | 1124 Handle<AccessorInfo> callback, |
| 1423 String* name, | 1125 Handle<String> name, |
| 1424 Label* miss) { | 1126 Label* miss) { |
| 1425 // Check that the receiver isn't a smi. | 1127 // Check that the receiver isn't a smi. |
| 1426 __ JumpIfSmi(receiver, miss); | 1128 __ JumpIfSmi(receiver, miss); |
| 1427 | 1129 |
| 1428 // Check that the maps haven't changed. | 1130 // Check that the maps haven't changed. |
| 1429 Register reg = | 1131 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
| 1430 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1132 scratch2, scratch3, name, miss); |
| 1431 name, miss); | |
| 1432 | 1133 |
| 1433 // Build AccessorInfo::args_ list on the stack and push property name below | 1134 // Build AccessorInfo::args_ list on the stack and push property name below |
| 1434 // the exit frame to make GC aware of them and store pointers to them. | 1135 // the exit frame to make GC aware of them and store pointers to them. |
| 1435 __ push(receiver); | 1136 __ push(receiver); |
| 1436 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ | 1137 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
| 1437 Handle<AccessorInfo> callback_handle(callback); | 1138 if (heap()->InNewSpace(callback->data())) { |
| 1438 if (heap()->InNewSpace(callback_handle->data())) { | 1139 __ Move(scratch3, callback); |
| 1439 __ Move(scratch3, callback_handle); | |
| 1440 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); | 1140 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); |
| 1441 } else { | 1141 } else { |
| 1442 __ Move(scratch3, Handle<Object>(callback_handle->data())); | 1142 __ Move(scratch3, Handle<Object>(callback->data())); |
| 1443 } | 1143 } |
| 1444 __ Push(reg, scratch3, name_reg); | 1144 __ Push(reg, scratch3, name_reg); |
| 1445 __ mov(r0, sp); // r0 = Handle<String> | 1145 __ mov(r0, sp); // r0 = Handle<String> |
| 1446 | 1146 |
| 1447 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
| 1448 ApiFunction fun(getter_address); | |
| 1449 | |
| 1450 const int kApiStackSpace = 1; | 1147 const int kApiStackSpace = 1; |
| 1451 | |
| 1452 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 1148 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
| 1453 __ EnterExitFrame(false, kApiStackSpace); | 1149 __ EnterExitFrame(false, kApiStackSpace); |
| 1454 | 1150 |
| 1455 // Create AccessorInfo instance on the stack above the exit frame with | 1151 // Create AccessorInfo instance on the stack above the exit frame with |
| 1456 // scratch2 (internal::Object **args_) as the data. | 1152 // scratch2 (internal::Object **args_) as the data. |
| 1457 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); | 1153 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); |
| 1458 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& | 1154 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& |
| 1459 | 1155 |
| 1460 // Emitting a stub call may try to allocate (if the code is not | 1156 // Emitting a stub call may try to allocate (if the code is not |
|
ulan
2011/10/27 10:10:26
Old comment.
Kevin Millikin (Chromium)
2011/10/27 10:53:43
Thanks.
| |
| 1461 // already generated). Do not allow the assembler to perform a | 1157 // already generated). Do not allow the assembler to perform a |
| 1462 // garbage collection but instead return the allocation failure | 1158 // garbage collection but instead return the allocation failure |
| 1463 // object. | 1159 // object. |
| 1464 const int kStackUnwindSpace = 4; | 1160 const int kStackUnwindSpace = 4; |
| 1161 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
| 1162 ApiFunction fun(getter_address); | |
| 1465 ExternalReference ref = | 1163 ExternalReference ref = |
| 1466 ExternalReference(&fun, | 1164 ExternalReference(&fun, |
| 1467 ExternalReference::DIRECT_GETTER_CALL, | 1165 ExternalReference::DIRECT_GETTER_CALL, |
| 1468 masm()->isolate()); | 1166 masm()->isolate()); |
| 1469 return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 1167 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 1470 } | 1168 } |
| 1471 | 1169 |
| 1472 | 1170 |
| 1473 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1171 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
| 1474 JSObject* interceptor_holder, | 1172 Handle<JSObject> interceptor_holder, |
| 1475 LookupResult* lookup, | 1173 LookupResult* lookup, |
| 1476 Register receiver, | 1174 Register receiver, |
| 1477 Register name_reg, | 1175 Register name_reg, |
| 1478 Register scratch1, | 1176 Register scratch1, |
| 1479 Register scratch2, | 1177 Register scratch2, |
| 1480 Register scratch3, | 1178 Register scratch3, |
| 1481 String* name, | 1179 Handle<String> name, |
| 1482 Label* miss) { | 1180 Label* miss) { |
| 1483 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1181 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1484 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1182 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1485 | 1183 |
| 1486 // Check that the receiver isn't a smi. | 1184 // Check that the receiver isn't a smi. |
| 1487 __ JumpIfSmi(receiver, miss); | 1185 __ JumpIfSmi(receiver, miss); |
| 1488 | 1186 |
| 1489 // So far the most popular follow ups for interceptor loads are FIELD | 1187 // So far the most popular follow ups for interceptor loads are FIELD |
| 1490 // and CALLBACKS, so inline only them, other cases may be added | 1188 // and CALLBACKS, so inline only them, other cases may be added |
| 1491 // later. | 1189 // later. |
| 1492 bool compile_followup_inline = false; | 1190 bool compile_followup_inline = false; |
| 1493 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1191 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 1494 if (lookup->type() == FIELD) { | 1192 if (lookup->type() == FIELD) { |
| 1495 compile_followup_inline = true; | 1193 compile_followup_inline = true; |
| 1496 } else if (lookup->type() == CALLBACKS && | 1194 } else if (lookup->type() == CALLBACKS && |
| 1497 lookup->GetCallbackObject()->IsAccessorInfo() && | 1195 lookup->GetCallbackObject()->IsAccessorInfo()) { |
| 1498 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1196 compile_followup_inline = |
|
ulan
2011/10/27 10:10:26
Nitpick: the old code does (compile_followup_inlin
Kevin Millikin (Chromium)
2011/10/27 10:53:43
There's no reason to preserve the implementation.
| |
| 1499 compile_followup_inline = true; | 1197 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; |
| 1500 } | 1198 } |
| 1501 } | 1199 } |
| 1502 | 1200 |
| 1503 if (compile_followup_inline) { | 1201 if (compile_followup_inline) { |
| 1504 // Compile the interceptor call, followed by inline code to load the | 1202 // Compile the interceptor call, followed by inline code to load the |
| 1505 // property from further up the prototype chain if the call fails. | 1203 // property from further up the prototype chain if the call fails. |
| 1506 // Check that the maps haven't changed. | 1204 // Check that the maps haven't changed. |
| 1507 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1205 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
| 1508 scratch1, scratch2, scratch3, | 1206 scratch1, scratch2, scratch3, |
| 1509 name, miss); | 1207 name, miss); |
| 1510 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1208 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
| 1511 | 1209 |
| 1512 // Save necessary data before invoking an interceptor. | 1210 // Save necessary data before invoking an interceptor. |
| 1513 // Requires a frame to make GC aware of pushed pointers. | 1211 // Requires a frame to make GC aware of pushed pointers. |
| 1514 { | 1212 { |
| 1515 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1213 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1516 | |
| 1517 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1214 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1518 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1215 // CALLBACKS case needs a receiver to be passed into C++ callback. |
| 1519 __ Push(receiver, holder_reg, name_reg); | 1216 __ Push(receiver, holder_reg, name_reg); |
| 1520 } else { | 1217 } else { |
| 1521 __ Push(holder_reg, name_reg); | 1218 __ Push(holder_reg, name_reg); |
| 1522 } | 1219 } |
| 1523 | |
| 1524 // Invoke an interceptor. Note: map checks from receiver to | 1220 // Invoke an interceptor. Note: map checks from receiver to |
| 1525 // interceptor's holder has been compiled before (see a caller | 1221 // interceptor's holder has been compiled before (see a caller |
| 1526 // of this method.) | 1222 // of this method.) |
| 1527 CompileCallLoadPropertyWithInterceptor(masm(), | 1223 CompileCallLoadPropertyWithInterceptor(masm(), |
| 1528 receiver, | 1224 receiver, |
| 1529 holder_reg, | 1225 holder_reg, |
| 1530 name_reg, | 1226 name_reg, |
| 1531 interceptor_holder); | 1227 interceptor_holder); |
| 1532 | |
| 1533 // Check if interceptor provided a value for property. If it's | 1228 // Check if interceptor provided a value for property. If it's |
| 1534 // the case, return immediately. | 1229 // the case, return immediately. |
| 1535 Label interceptor_failed; | 1230 Label interceptor_failed; |
| 1536 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); | 1231 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1537 __ cmp(r0, scratch1); | 1232 __ cmp(r0, scratch1); |
| 1538 __ b(eq, &interceptor_failed); | 1233 __ b(eq, &interceptor_failed); |
| 1539 frame_scope.GenerateLeaveFrame(); | 1234 frame_scope.GenerateLeaveFrame(); |
| 1540 __ Ret(); | 1235 __ Ret(); |
| 1541 | 1236 |
| 1542 __ bind(&interceptor_failed); | 1237 __ bind(&interceptor_failed); |
| 1543 __ pop(name_reg); | 1238 __ pop(name_reg); |
| 1544 __ pop(holder_reg); | 1239 __ pop(holder_reg); |
| 1545 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1240 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1546 __ pop(receiver); | 1241 __ pop(receiver); |
| 1547 } | 1242 } |
| 1548 | |
| 1549 // Leave the internal frame. | 1243 // Leave the internal frame. |
| 1550 } | 1244 } |
| 1551 | |
| 1552 // Check that the maps from interceptor's holder to lookup's holder | 1245 // Check that the maps from interceptor's holder to lookup's holder |
| 1553 // haven't changed. And load lookup's holder into |holder| register. | 1246 // haven't changed. And load lookup's holder into |holder| register. |
| 1554 if (interceptor_holder != lookup->holder()) { | 1247 if (*interceptor_holder != lookup->holder()) { |
| 1555 holder_reg = CheckPrototypes(interceptor_holder, | 1248 holder_reg = CheckPrototypes(interceptor_holder, |
| 1556 holder_reg, | 1249 holder_reg, |
| 1557 lookup->holder(), | 1250 Handle<JSObject>(lookup->holder()), |
| 1558 scratch1, | 1251 scratch1, |
| 1559 scratch2, | 1252 scratch2, |
| 1560 scratch3, | 1253 scratch3, |
| 1561 name, | 1254 name, |
| 1562 miss); | 1255 miss); |
| 1563 } | 1256 } |
| 1564 | 1257 |
| 1565 if (lookup->type() == FIELD) { | 1258 if (lookup->type() == FIELD) { |
| 1566 // We found FIELD property in prototype chain of interceptor's holder. | 1259 // We found FIELD property in prototype chain of interceptor's holder. |
| 1567 // Retrieve a field from field's holder. | 1260 // Retrieve a field from field's holder. |
| 1568 GenerateFastPropertyLoad(masm(), r0, holder_reg, | 1261 GenerateFastPropertyLoad(masm(), r0, holder_reg, |
| 1569 Handle<JSObject>(lookup->holder()), | 1262 Handle<JSObject>(lookup->holder()), |
| 1570 lookup->GetFieldIndex()); | 1263 lookup->GetFieldIndex()); |
| 1571 __ Ret(); | 1264 __ Ret(); |
| 1572 } else { | 1265 } else { |
| 1573 // We found CALLBACKS property in prototype chain of interceptor's | 1266 // We found CALLBACKS property in prototype chain of interceptor's |
| 1574 // holder. | 1267 // holder. |
| 1575 ASSERT(lookup->type() == CALLBACKS); | 1268 ASSERT(lookup->type() == CALLBACKS); |
| 1576 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1269 Handle<AccessorInfo> callback( |
| 1577 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1270 AccessorInfo::cast(lookup->GetCallbackObject())); |
| 1578 ASSERT(callback != NULL); | |
| 1579 ASSERT(callback->getter() != NULL); | 1271 ASSERT(callback->getter() != NULL); |
| 1580 | 1272 |
| 1581 // Tail call to runtime. | 1273 // Tail call to runtime. |
| 1582 // Important invariant in CALLBACKS case: the code above must be | 1274 // Important invariant in CALLBACKS case: the code above must be |
| 1583 // structured to never clobber |receiver| register. | 1275 // structured to never clobber |receiver| register. |
| 1584 __ Move(scratch2, Handle<AccessorInfo>(callback)); | 1276 __ Move(scratch2, callback); |
| 1585 // holder_reg is either receiver or scratch1. | 1277 // holder_reg is either receiver or scratch1. |
| 1586 if (!receiver.is(holder_reg)) { | 1278 if (!receiver.is(holder_reg)) { |
| 1587 ASSERT(scratch1.is(holder_reg)); | 1279 ASSERT(scratch1.is(holder_reg)); |
| 1588 __ Push(receiver, holder_reg); | 1280 __ Push(receiver, holder_reg); |
| 1589 __ ldr(scratch3, | 1281 __ ldr(scratch3, |
| 1590 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); | 1282 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); |
| 1591 __ Push(scratch3, scratch2, name_reg); | 1283 __ Push(scratch3, scratch2, name_reg); |
| 1592 } else { | 1284 } else { |
| 1593 __ push(receiver); | 1285 __ push(receiver); |
| 1594 __ ldr(scratch3, | 1286 __ ldr(scratch3, |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1619 | 1311 |
| 1620 | 1312 |
| 1621 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { | 1313 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1622 if (kind_ == Code::KEYED_CALL_IC) { | 1314 if (kind_ == Code::KEYED_CALL_IC) { |
| 1623 __ cmp(r2, Operand(name)); | 1315 __ cmp(r2, Operand(name)); |
| 1624 __ b(ne, miss); | 1316 __ b(ne, miss); |
| 1625 } | 1317 } |
| 1626 } | 1318 } |
| 1627 | 1319 |
| 1628 | 1320 |
| 1629 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1321 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, |
| 1630 JSObject* holder, | 1322 Handle<JSObject> holder, |
| 1631 String* name, | 1323 Handle<String> name, |
| 1632 Label* miss) { | 1324 Label* miss) { |
| 1633 ASSERT(holder->IsGlobalObject()); | 1325 ASSERT(holder->IsGlobalObject()); |
| 1634 | 1326 |
| 1635 // Get the number of arguments. | 1327 // Get the number of arguments. |
| 1636 const int argc = arguments().immediate(); | 1328 const int argc = arguments().immediate(); |
| 1637 | 1329 |
| 1638 // Get the receiver from the stack. | 1330 // Get the receiver from the stack. |
| 1639 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1331 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1640 | 1332 |
| 1641 // If the object is the holder then we know that it's a global | 1333 // If the object is the holder then we know that it's a global |
| 1642 // object which can only happen for contextual calls. In this case, | 1334 // object which can only happen for contextual calls. In this case, |
| 1643 // the receiver cannot be a smi. | 1335 // the receiver cannot be a smi. |
| 1644 if (object != holder) { | 1336 if (!object.is_identical_to(holder)) { |
| 1645 __ JumpIfSmi(r0, miss); | 1337 __ JumpIfSmi(r0, miss); |
| 1646 } | 1338 } |
| 1647 | 1339 |
| 1648 // Check that the maps haven't changed. | 1340 // Check that the maps haven't changed. |
| 1649 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); | 1341 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); |
| 1650 } | 1342 } |
| 1651 | 1343 |
| 1652 | 1344 |
| 1653 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1345 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1654 JSFunction* function, | 1346 Handle<JSGlobalPropertyCell> cell, |
| 1655 Label* miss) { | 1347 Handle<JSFunction> function, |
| 1348 Label* miss) { | |
| 1656 // Get the value from the cell. | 1349 // Get the value from the cell. |
| 1657 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1350 __ mov(r3, Operand(cell)); |
| 1658 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 1351 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
| 1659 | 1352 |
| 1660 // Check that the cell contains the same function. | 1353 // Check that the cell contains the same function. |
| 1661 if (heap()->InNewSpace(function)) { | 1354 if (heap()->InNewSpace(*function)) { |
| 1662 // We can't embed a pointer to a function in new space so we have | 1355 // We can't embed a pointer to a function in new space so we have |
| 1663 // to verify that the shared function info is unchanged. This has | 1356 // to verify that the shared function info is unchanged. This has |
| 1664 // the nice side effect that multiple closures based on the same | 1357 // the nice side effect that multiple closures based on the same |
| 1665 // function can all use this call IC. Before we load through the | 1358 // function can all use this call IC. Before we load through the |
| 1666 // function, we have to verify that it still is a function. | 1359 // function, we have to verify that it still is a function. |
| 1667 __ JumpIfSmi(r1, miss); | 1360 __ JumpIfSmi(r1, miss); |
| 1668 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 1361 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 1669 __ b(ne, miss); | 1362 __ b(ne, miss); |
| 1670 | 1363 |
| 1671 // Check the shared function info. Make sure it hasn't changed. | 1364 // Check the shared function info. Make sure it hasn't changed. |
| 1672 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1365 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
| 1673 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1366 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1674 __ cmp(r4, r3); | 1367 __ cmp(r4, r3); |
| 1675 __ b(ne, miss); | |
| 1676 } else { | 1368 } else { |
| 1677 __ cmp(r1, Operand(Handle<JSFunction>(function))); | 1369 __ cmp(r1, Operand(function)); |
| 1678 __ b(ne, miss); | |
| 1679 } | 1370 } |
| 1371 __ b(ne, miss); | |
| 1680 } | 1372 } |
| 1681 | 1373 |
| 1682 | 1374 |
| 1683 void CallStubCompiler::GenerateMissBranch() { | 1375 void CallStubCompiler::GenerateMissBranch() { |
| 1684 Handle<Code> code = | 1376 Handle<Code> code = |
| 1685 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1377 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1686 kind_, | 1378 kind_, |
| 1687 extra_state_); | 1379 extra_state_); |
| 1688 __ Jump(code, RelocInfo::CODE_TARGET); | 1380 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1689 } | 1381 } |
| 1690 | 1382 |
| 1691 | 1383 |
| 1692 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 1693 // handlified. | |
| 1694 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { | |
| 1695 MaybeObject* maybe_obj = | |
| 1696 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | |
| 1697 kind_, | |
| 1698 extra_state_); | |
| 1699 Object* obj; | |
| 1700 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 1701 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | |
| 1702 return obj; | |
| 1703 } | |
| 1704 | |
| 1705 | |
| 1706 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1384 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1707 Handle<JSObject> holder, | 1385 Handle<JSObject> holder, |
| 1708 int index, | 1386 int index, |
| 1709 Handle<String> name) { | 1387 Handle<String> name) { |
| 1710 // ----------- S t a t e ------------- | 1388 // ----------- S t a t e ------------- |
| 1711 // -- r2 : name | 1389 // -- r2 : name |
| 1712 // -- lr : return address | 1390 // -- lr : return address |
| 1713 // ----------------------------------- | 1391 // ----------------------------------- |
| 1714 Label miss; | 1392 Label miss; |
| 1715 | 1393 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1730 | 1408 |
| 1731 // Handle call cache miss. | 1409 // Handle call cache miss. |
| 1732 __ bind(&miss); | 1410 __ bind(&miss); |
| 1733 GenerateMissBranch(); | 1411 GenerateMissBranch(); |
| 1734 | 1412 |
| 1735 // Return the generated code. | 1413 // Return the generated code. |
| 1736 return GetCode(FIELD, name); | 1414 return GetCode(FIELD, name); |
| 1737 } | 1415 } |
| 1738 | 1416 |
| 1739 | 1417 |
| 1740 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1418 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1741 JSObject* holder, | 1419 Handle<Object> object, |
| 1742 JSGlobalPropertyCell* cell, | 1420 Handle<JSObject> holder, |
| 1743 JSFunction* function, | 1421 Handle<JSGlobalPropertyCell> cell, |
| 1744 String* name) { | 1422 Handle<JSFunction> function, |
| 1423 Handle<String> name) { | |
| 1745 // ----------- S t a t e ------------- | 1424 // ----------- S t a t e ------------- |
| 1746 // -- r2 : name | 1425 // -- r2 : name |
| 1747 // -- lr : return address | 1426 // -- lr : return address |
| 1748 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1427 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1749 // -- ... | 1428 // -- ... |
| 1750 // -- sp[argc * 4] : receiver | 1429 // -- sp[argc * 4] : receiver |
| 1751 // ----------------------------------- | 1430 // ----------------------------------- |
| 1752 | 1431 |
| 1753 // If object is not an array, bail out to regular call. | 1432 // If object is not an array, bail out to regular call. |
| 1754 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1433 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1755 | 1434 |
| 1756 Label miss; | 1435 Label miss; |
| 1757 | 1436 GenerateNameCheck(name, &miss); |
| 1758 GenerateNameCheck(Handle<String>(name), &miss); | |
| 1759 | 1437 |
| 1760 Register receiver = r1; | 1438 Register receiver = r1; |
| 1761 | |
| 1762 // Get the receiver from the stack | 1439 // Get the receiver from the stack |
| 1763 const int argc = arguments().immediate(); | 1440 const int argc = arguments().immediate(); |
| 1764 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1441 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1765 | 1442 |
| 1766 // Check that the receiver isn't a smi. | 1443 // Check that the receiver isn't a smi. |
| 1767 __ JumpIfSmi(receiver, &miss); | 1444 __ JumpIfSmi(receiver, &miss); |
| 1768 | 1445 |
| 1769 // Check that the maps haven't changed. | 1446 // Check that the maps haven't changed. |
| 1770 CheckPrototypes(JSObject::cast(object), receiver, | 1447 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4, |
| 1771 holder, r3, r0, r4, name, &miss); | 1448 name, &miss); |
| 1772 | 1449 |
| 1773 if (argc == 0) { | 1450 if (argc == 0) { |
| 1774 // Nothing to do, just return the length. | 1451 // Nothing to do, just return the length. |
| 1775 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1452 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1776 __ Drop(argc + 1); | 1453 __ Drop(argc + 1); |
| 1777 __ Ret(); | 1454 __ Ret(); |
| 1778 } else { | 1455 } else { |
| 1779 Label call_builtin; | 1456 Label call_builtin; |
| 1780 | |
| 1781 Register elements = r3; | 1457 Register elements = r3; |
| 1782 Register end_elements = r5; | 1458 Register end_elements = r5; |
| 1783 | |
| 1784 // Get the elements array of the object. | 1459 // Get the elements array of the object. |
| 1785 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1460 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1786 | 1461 |
| 1787 // Check that the elements are in fast mode and writable. | 1462 // Check that the elements are in fast mode and writable. |
| 1788 __ CheckMap(elements, | 1463 __ CheckMap(elements, |
| 1789 r0, | 1464 r0, |
| 1790 Heap::kFixedArrayMapRootIndex, | 1465 Heap::kFixedArrayMapRootIndex, |
| 1791 &call_builtin, | 1466 &call_builtin, |
| 1792 DONT_DO_SMI_CHECK); | 1467 DONT_DO_SMI_CHECK); |
| 1793 | 1468 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1914 } | 1589 } |
| 1915 __ bind(&call_builtin); | 1590 __ bind(&call_builtin); |
| 1916 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1591 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1917 masm()->isolate()), | 1592 masm()->isolate()), |
| 1918 argc + 1, | 1593 argc + 1, |
| 1919 1); | 1594 1); |
| 1920 } | 1595 } |
| 1921 | 1596 |
| 1922 // Handle call cache miss. | 1597 // Handle call cache miss. |
| 1923 __ bind(&miss); | 1598 __ bind(&miss); |
| 1924 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1599 GenerateMissBranch(); |
| 1925 if (maybe_result->IsFailure()) return maybe_result; | |
| 1926 | 1600 |
| 1927 // Return the generated code. | 1601 // Return the generated code. |
| 1928 return TryGetCode(function); | 1602 return GetCode(function); |
| 1929 } | 1603 } |
| 1930 | 1604 |
| 1931 | 1605 |
| 1932 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1606 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1933 JSObject* holder, | 1607 Handle<Object> object, |
| 1934 JSGlobalPropertyCell* cell, | 1608 Handle<JSObject> holder, |
| 1935 JSFunction* function, | 1609 Handle<JSGlobalPropertyCell> cell, |
| 1936 String* name) { | 1610 Handle<JSFunction> function, |
| 1611 Handle<String> name) { | |
| 1937 // ----------- S t a t e ------------- | 1612 // ----------- S t a t e ------------- |
| 1938 // -- r2 : name | 1613 // -- r2 : name |
| 1939 // -- lr : return address | 1614 // -- lr : return address |
| 1940 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1615 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1941 // -- ... | 1616 // -- ... |
| 1942 // -- sp[argc * 4] : receiver | 1617 // -- sp[argc * 4] : receiver |
| 1943 // ----------------------------------- | 1618 // ----------------------------------- |
| 1944 | 1619 |
| 1945 // If object is not an array, bail out to regular call. | 1620 // If object is not an array, bail out to regular call. |
| 1946 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1621 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1947 | 1622 |
| 1948 Label miss, return_undefined, call_builtin; | 1623 Label miss, return_undefined, call_builtin; |
| 1949 | |
| 1950 Register receiver = r1; | 1624 Register receiver = r1; |
| 1951 Register elements = r3; | 1625 Register elements = r3; |
| 1952 | 1626 GenerateNameCheck(name, &miss); |
| 1953 GenerateNameCheck(Handle<String>(name), &miss); | |
| 1954 | 1627 |
| 1955 // Get the receiver from the stack | 1628 // Get the receiver from the stack |
| 1956 const int argc = arguments().immediate(); | 1629 const int argc = arguments().immediate(); |
| 1957 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1630 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1958 | |
| 1959 // Check that the receiver isn't a smi. | 1631 // Check that the receiver isn't a smi. |
| 1960 __ JumpIfSmi(receiver, &miss); | 1632 __ JumpIfSmi(receiver, &miss); |
| 1961 | 1633 |
| 1962 // Check that the maps haven't changed. | 1634 // Check that the maps haven't changed. |
| 1963 CheckPrototypes(JSObject::cast(object), | 1635 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, |
| 1964 receiver, holder, elements, r4, r0, name, &miss); | 1636 r4, r0, name, &miss); |
| 1965 | 1637 |
| 1966 // Get the elements array of the object. | 1638 // Get the elements array of the object. |
| 1967 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1639 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1968 | 1640 |
| 1969 // Check that the elements are in fast mode and writable. | 1641 // Check that the elements are in fast mode and writable. |
| 1970 __ CheckMap(elements, | 1642 __ CheckMap(elements, |
| 1971 r0, | 1643 r0, |
| 1972 Heap::kFixedArrayMapRootIndex, | 1644 Heap::kFixedArrayMapRootIndex, |
| 1973 &call_builtin, | 1645 &call_builtin, |
| 1974 DONT_DO_SMI_CHECK); | 1646 DONT_DO_SMI_CHECK); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 2003 __ Ret(); | 1675 __ Ret(); |
| 2004 | 1676 |
| 2005 __ bind(&call_builtin); | 1677 __ bind(&call_builtin); |
| 2006 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, | 1678 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, |
| 2007 masm()->isolate()), | 1679 masm()->isolate()), |
| 2008 argc + 1, | 1680 argc + 1, |
| 2009 1); | 1681 1); |
| 2010 | 1682 |
| 2011 // Handle call cache miss. | 1683 // Handle call cache miss. |
| 2012 __ bind(&miss); | 1684 __ bind(&miss); |
| 2013 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1685 GenerateMissBranch(); |
| 2014 if (maybe_result->IsFailure()) return maybe_result; | |
| 2015 | 1686 |
| 2016 // Return the generated code. | 1687 // Return the generated code. |
| 2017 return TryGetCode(function); | 1688 return GetCode(function); |
| 2018 } | 1689 } |
| 2019 | 1690 |
| 2020 | 1691 |
| 2021 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1692 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2022 Object* object, | 1693 Handle<Object> object, |
| 2023 JSObject* holder, | 1694 Handle<JSObject> holder, |
| 2024 JSGlobalPropertyCell* cell, | 1695 Handle<JSGlobalPropertyCell> cell, |
| 2025 JSFunction* function, | 1696 Handle<JSFunction> function, |
| 2026 String* name) { | 1697 Handle<String> name) { |
| 2027 // ----------- S t a t e ------------- | 1698 // ----------- S t a t e ------------- |
| 2028 // -- r2 : function name | 1699 // -- r2 : function name |
| 2029 // -- lr : return address | 1700 // -- lr : return address |
| 2030 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1701 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2031 // -- ... | 1702 // -- ... |
| 2032 // -- sp[argc * 4] : receiver | 1703 // -- sp[argc * 4] : receiver |
| 2033 // ----------------------------------- | 1704 // ----------------------------------- |
| 2034 | 1705 |
| 2035 // If object is not a string, bail out to regular call. | 1706 // If object is not a string, bail out to regular call. |
| 2036 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1707 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2037 | 1708 |
| 2038 const int argc = arguments().immediate(); | 1709 const int argc = arguments().immediate(); |
| 2039 | |
| 2040 Label miss; | 1710 Label miss; |
| 2041 Label name_miss; | 1711 Label name_miss; |
| 2042 Label index_out_of_range; | 1712 Label index_out_of_range; |
| 2043 Label* index_out_of_range_label = &index_out_of_range; | 1713 Label* index_out_of_range_label = &index_out_of_range; |
| 2044 | 1714 |
| 2045 if (kind_ == Code::CALL_IC && | 1715 if (kind_ == Code::CALL_IC && |
| 2046 (CallICBase::StringStubState::decode(extra_state_) == | 1716 (CallICBase::StringStubState::decode(extra_state_) == |
| 2047 DEFAULT_STRING_STUB)) { | 1717 DEFAULT_STRING_STUB)) { |
| 2048 index_out_of_range_label = &miss; | 1718 index_out_of_range_label = &miss; |
| 2049 } | 1719 } |
| 2050 | 1720 GenerateNameCheck(name, &name_miss); |
| 2051 GenerateNameCheck(Handle<String>(name), &name_miss); | |
| 2052 | 1721 |
| 2053 // Check that the maps starting from the prototype haven't changed. | 1722 // Check that the maps starting from the prototype haven't changed. |
| 2054 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1723 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2055 Context::STRING_FUNCTION_INDEX, | 1724 Context::STRING_FUNCTION_INDEX, |
| 2056 r0, | 1725 r0, |
| 2057 &miss); | 1726 &miss); |
| 2058 ASSERT(object != holder); | 1727 ASSERT(object != holder); |
| 2059 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, | 1728 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2060 r1, r3, r4, name, &miss); | 1729 r0, holder, r1, r3, r4, name, &miss); |
| 2061 | 1730 |
| 2062 Register receiver = r1; | 1731 Register receiver = r1; |
| 2063 Register index = r4; | 1732 Register index = r4; |
| 2064 Register scratch = r3; | 1733 Register scratch = r3; |
| 2065 Register result = r0; | 1734 Register result = r0; |
| 2066 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1735 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2067 if (argc > 0) { | 1736 if (argc > 0) { |
| 2068 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1737 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2069 } else { | 1738 } else { |
| 2070 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1739 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2071 } | 1740 } |
| 2072 | 1741 |
| 2073 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1742 StringCharCodeAtGenerator generator(receiver, |
| 2074 index, | 1743 index, |
| 2075 scratch, | 1744 scratch, |
| 2076 result, | 1745 result, |
| 2077 &miss, // When not a string. | 1746 &miss, // When not a string. |
| 2078 &miss, // When not a number. | 1747 &miss, // When not a number. |
| 2079 index_out_of_range_label, | 1748 index_out_of_range_label, |
| 2080 STRING_INDEX_IS_NUMBER); | 1749 STRING_INDEX_IS_NUMBER); |
| 2081 char_code_at_generator.GenerateFast(masm()); | 1750 generator.GenerateFast(masm()); |
| 2082 __ Drop(argc + 1); | 1751 __ Drop(argc + 1); |
| 2083 __ Ret(); | 1752 __ Ret(); |
| 2084 | 1753 |
| 2085 StubRuntimeCallHelper call_helper; | 1754 StubRuntimeCallHelper call_helper; |
| 2086 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1755 generator.GenerateSlow(masm(), call_helper); |
| 2087 | 1756 |
| 2088 if (index_out_of_range.is_linked()) { | 1757 if (index_out_of_range.is_linked()) { |
| 2089 __ bind(&index_out_of_range); | 1758 __ bind(&index_out_of_range); |
| 2090 __ LoadRoot(r0, Heap::kNanValueRootIndex); | 1759 __ LoadRoot(r0, Heap::kNanValueRootIndex); |
| 2091 __ Drop(argc + 1); | 1760 __ Drop(argc + 1); |
| 2092 __ Ret(); | 1761 __ Ret(); |
| 2093 } | 1762 } |
| 2094 | 1763 |
| 2095 __ bind(&miss); | 1764 __ bind(&miss); |
| 2096 // Restore function name in r2. | 1765 // Restore function name in r2. |
| 2097 __ Move(r2, Handle<String>(name)); | 1766 __ Move(r2, name); |
| 2098 __ bind(&name_miss); | 1767 __ bind(&name_miss); |
| 2099 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1768 GenerateMissBranch(); |
| 2100 if (maybe_result->IsFailure()) return maybe_result; | |
| 2101 | 1769 |
| 2102 // Return the generated code. | 1770 // Return the generated code. |
| 2103 return TryGetCode(function); | 1771 return GetCode(function); |
| 2104 } | 1772 } |
| 2105 | 1773 |
| 2106 | 1774 |
| 2107 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1775 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2108 Object* object, | 1776 Handle<Object> object, |
| 2109 JSObject* holder, | 1777 Handle<JSObject> holder, |
| 2110 JSGlobalPropertyCell* cell, | 1778 Handle<JSGlobalPropertyCell> cell, |
| 2111 JSFunction* function, | 1779 Handle<JSFunction> function, |
| 2112 String* name) { | 1780 Handle<String> name) { |
| 2113 // ----------- S t a t e ------------- | 1781 // ----------- S t a t e ------------- |
| 2114 // -- r2 : function name | 1782 // -- r2 : function name |
| 2115 // -- lr : return address | 1783 // -- lr : return address |
| 2116 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1784 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2117 // -- ... | 1785 // -- ... |
| 2118 // -- sp[argc * 4] : receiver | 1786 // -- sp[argc * 4] : receiver |
| 2119 // ----------------------------------- | 1787 // ----------------------------------- |
| 2120 | 1788 |
| 2121 // If object is not a string, bail out to regular call. | 1789 // If object is not a string, bail out to regular call. |
| 2122 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1790 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2123 | 1791 |
| 2124 const int argc = arguments().immediate(); | 1792 const int argc = arguments().immediate(); |
| 2125 | |
| 2126 Label miss; | 1793 Label miss; |
| 2127 Label name_miss; | 1794 Label name_miss; |
| 2128 Label index_out_of_range; | 1795 Label index_out_of_range; |
| 2129 Label* index_out_of_range_label = &index_out_of_range; | 1796 Label* index_out_of_range_label = &index_out_of_range; |
| 2130 | |
| 2131 if (kind_ == Code::CALL_IC && | 1797 if (kind_ == Code::CALL_IC && |
| 2132 (CallICBase::StringStubState::decode(extra_state_) == | 1798 (CallICBase::StringStubState::decode(extra_state_) == |
| 2133 DEFAULT_STRING_STUB)) { | 1799 DEFAULT_STRING_STUB)) { |
| 2134 index_out_of_range_label = &miss; | 1800 index_out_of_range_label = &miss; |
| 2135 } | 1801 } |
| 2136 | 1802 GenerateNameCheck(name, &name_miss); |
| 2137 GenerateNameCheck(Handle<String>(name), &name_miss); | |
| 2138 | 1803 |
| 2139 // Check that the maps starting from the prototype haven't changed. | 1804 // Check that the maps starting from the prototype haven't changed. |
| 2140 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1805 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2141 Context::STRING_FUNCTION_INDEX, | 1806 Context::STRING_FUNCTION_INDEX, |
| 2142 r0, | 1807 r0, |
| 2143 &miss); | 1808 &miss); |
| 2144 ASSERT(object != holder); | 1809 ASSERT(object != holder); |
| 2145 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, | 1810 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2146 r1, r3, r4, name, &miss); | 1811 r0, holder, r1, r3, r4, name, &miss); |
| 2147 | 1812 |
| 2148 Register receiver = r0; | 1813 Register receiver = r0; |
| 2149 Register index = r4; | 1814 Register index = r4; |
| 2150 Register scratch1 = r1; | 1815 Register scratch1 = r1; |
| 2151 Register scratch2 = r3; | 1816 Register scratch2 = r3; |
| 2152 Register result = r0; | 1817 Register result = r0; |
| 2153 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1818 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2154 if (argc > 0) { | 1819 if (argc > 0) { |
| 2155 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1820 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2156 } else { | 1821 } else { |
| 2157 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1822 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2158 } | 1823 } |
| 2159 | 1824 |
| 2160 StringCharAtGenerator char_at_generator(receiver, | 1825 StringCharAtGenerator generator(receiver, |
| 2161 index, | 1826 index, |
| 2162 scratch1, | 1827 scratch1, |
| 2163 scratch2, | 1828 scratch2, |
| 2164 result, | 1829 result, |
| 2165 &miss, // When not a string. | 1830 &miss, // When not a string. |
| 2166 &miss, // When not a number. | 1831 &miss, // When not a number. |
| 2167 index_out_of_range_label, | 1832 index_out_of_range_label, |
| 2168 STRING_INDEX_IS_NUMBER); | 1833 STRING_INDEX_IS_NUMBER); |
| 2169 char_at_generator.GenerateFast(masm()); | 1834 generator.GenerateFast(masm()); |
| 2170 __ Drop(argc + 1); | 1835 __ Drop(argc + 1); |
| 2171 __ Ret(); | 1836 __ Ret(); |
| 2172 | 1837 |
| 2173 StubRuntimeCallHelper call_helper; | 1838 StubRuntimeCallHelper call_helper; |
| 2174 char_at_generator.GenerateSlow(masm(), call_helper); | 1839 generator.GenerateSlow(masm(), call_helper); |
| 2175 | 1840 |
| 2176 if (index_out_of_range.is_linked()) { | 1841 if (index_out_of_range.is_linked()) { |
| 2177 __ bind(&index_out_of_range); | 1842 __ bind(&index_out_of_range); |
| 2178 __ LoadRoot(r0, Heap::kEmptyStringRootIndex); | 1843 __ LoadRoot(r0, Heap::kEmptyStringRootIndex); |
| 2179 __ Drop(argc + 1); | 1844 __ Drop(argc + 1); |
| 2180 __ Ret(); | 1845 __ Ret(); |
| 2181 } | 1846 } |
| 2182 | 1847 |
| 2183 __ bind(&miss); | 1848 __ bind(&miss); |
| 2184 // Restore function name in r2. | 1849 // Restore function name in r2. |
| 2185 __ Move(r2, Handle<String>(name)); | 1850 __ Move(r2, name); |
| 2186 __ bind(&name_miss); | 1851 __ bind(&name_miss); |
| 2187 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1852 GenerateMissBranch(); |
| 2188 if (maybe_result->IsFailure()) return maybe_result; | |
| 2189 | 1853 |
| 2190 // Return the generated code. | 1854 // Return the generated code. |
| 2191 return TryGetCode(function); | 1855 return GetCode(function); |
| 2192 } | 1856 } |
| 2193 | 1857 |
| 2194 | 1858 |
| 2195 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 1859 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2196 Object* object, | 1860 Handle<Object> object, |
| 2197 JSObject* holder, | 1861 Handle<JSObject> holder, |
| 2198 JSGlobalPropertyCell* cell, | 1862 Handle<JSGlobalPropertyCell> cell, |
| 2199 JSFunction* function, | 1863 Handle<JSFunction> function, |
| 2200 String* name) { | 1864 Handle<String> name) { |
| 2201 // ----------- S t a t e ------------- | 1865 // ----------- S t a t e ------------- |
| 2202 // -- r2 : function name | 1866 // -- r2 : function name |
| 2203 // -- lr : return address | 1867 // -- lr : return address |
| 2204 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1868 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2205 // -- ... | 1869 // -- ... |
| 2206 // -- sp[argc * 4] : receiver | 1870 // -- sp[argc * 4] : receiver |
| 2207 // ----------------------------------- | 1871 // ----------------------------------- |
| 2208 | 1872 |
| 2209 const int argc = arguments().immediate(); | 1873 const int argc = arguments().immediate(); |
| 2210 | 1874 |
| 2211 // If the object is not a JSObject or we got an unexpected number of | 1875 // If the object is not a JSObject or we got an unexpected number of |
| 2212 // arguments, bail out to the regular call. | 1876 // arguments, bail out to the regular call. |
| 2213 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1877 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2214 | 1878 |
| 2215 Label miss; | 1879 Label miss; |
| 2216 GenerateNameCheck(Handle<String>(name), &miss); | 1880 GenerateNameCheck(name, &miss); |
| 2217 | 1881 |
| 2218 if (cell == NULL) { | 1882 if (cell.is_null()) { |
| 2219 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 1883 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2220 | 1884 |
| 2221 STATIC_ASSERT(kSmiTag == 0); | 1885 STATIC_ASSERT(kSmiTag == 0); |
| 2222 __ JumpIfSmi(r1, &miss); | 1886 __ JumpIfSmi(r1, &miss); |
| 2223 | 1887 |
| 2224 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 1888 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
| 2225 &miss); | 1889 name, &miss); |
| 2226 } else { | 1890 } else { |
| 2227 ASSERT(cell->value() == function); | 1891 ASSERT(cell->value() == *function); |
| 2228 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1892 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1893 &miss); | |
| 2229 GenerateLoadFunctionFromCell(cell, function, &miss); | 1894 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2230 } | 1895 } |
| 2231 | 1896 |
| 2232 // Load the char code argument. | 1897 // Load the char code argument. |
| 2233 Register code = r1; | 1898 Register code = r1; |
| 2234 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); | 1899 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); |
| 2235 | 1900 |
| 2236 // Check the code is a smi. | 1901 // Check the code is a smi. |
| 2237 Label slow; | 1902 Label slow; |
| 2238 STATIC_ASSERT(kSmiTag == 0); | 1903 STATIC_ASSERT(kSmiTag == 0); |
| 2239 __ JumpIfNotSmi(code, &slow); | 1904 __ JumpIfNotSmi(code, &slow); |
| 2240 | 1905 |
| 2241 // Convert the smi code to uint16. | 1906 // Convert the smi code to uint16. |
| 2242 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 1907 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
| 2243 | 1908 |
| 2244 StringCharFromCodeGenerator char_from_code_generator(code, r0); | 1909 StringCharFromCodeGenerator generator(code, r0); |
| 2245 char_from_code_generator.GenerateFast(masm()); | 1910 generator.GenerateFast(masm()); |
| 2246 __ Drop(argc + 1); | 1911 __ Drop(argc + 1); |
| 2247 __ Ret(); | 1912 __ Ret(); |
| 2248 | 1913 |
| 2249 StubRuntimeCallHelper call_helper; | 1914 StubRuntimeCallHelper call_helper; |
| 2250 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1915 generator.GenerateSlow(masm(), call_helper); |
| 2251 | 1916 |
| 2252 // Tail call the full function. We do not have to patch the receiver | 1917 // Tail call the full function. We do not have to patch the receiver |
| 2253 // because the function makes no use of it. | 1918 // because the function makes no use of it. |
| 2254 __ bind(&slow); | 1919 __ bind(&slow); |
| 2255 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 1920 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2256 | 1921 |
| 2257 __ bind(&miss); | 1922 __ bind(&miss); |
| 2258 // r2: function name. | 1923 // r2: function name. |
| 2259 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1924 GenerateMissBranch(); |
| 2260 if (maybe_result->IsFailure()) return maybe_result; | |
| 2261 | 1925 |
| 2262 // Return the generated code. | 1926 // Return the generated code. |
| 2263 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1927 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2264 } | 1928 } |
| 2265 | 1929 |
| 2266 | 1930 |
| 2267 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 1931 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2268 JSObject* holder, | 1932 Handle<Object> object, |
| 2269 JSGlobalPropertyCell* cell, | 1933 Handle<JSObject> holder, |
| 2270 JSFunction* function, | 1934 Handle<JSGlobalPropertyCell> cell, |
| 2271 String* name) { | 1935 Handle<JSFunction> function, |
| 1936 Handle<String> name) { | |
| 2272 // ----------- S t a t e ------------- | 1937 // ----------- S t a t e ------------- |
| 2273 // -- r2 : function name | 1938 // -- r2 : function name |
| 2274 // -- lr : return address | 1939 // -- lr : return address |
| 2275 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1940 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2276 // -- ... | 1941 // -- ... |
| 2277 // -- sp[argc * 4] : receiver | 1942 // -- sp[argc * 4] : receiver |
| 2278 // ----------------------------------- | 1943 // ----------------------------------- |
| 2279 | 1944 |
| 2280 if (!CpuFeatures::IsSupported(VFP3)) { | 1945 if (!CpuFeatures::IsSupported(VFP3)) { |
| 2281 return heap()->undefined_value(); | 1946 return Handle<Code>::null(); |
| 2282 } | 1947 } |
| 2283 | 1948 |
| 2284 CpuFeatures::Scope scope_vfp3(VFP3); | 1949 CpuFeatures::Scope scope_vfp3(VFP3); |
| 2285 | |
| 2286 const int argc = arguments().immediate(); | 1950 const int argc = arguments().immediate(); |
| 2287 | |
| 2288 // If the object is not a JSObject or we got an unexpected number of | 1951 // If the object is not a JSObject or we got an unexpected number of |
| 2289 // arguments, bail out to the regular call. | 1952 // arguments, bail out to the regular call. |
| 2290 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1953 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2291 | 1954 |
| 2292 Label miss, slow; | 1955 Label miss, slow; |
| 2293 GenerateNameCheck(Handle<String>(name), &miss); | 1956 GenerateNameCheck(name, &miss); |
| 2294 | 1957 |
| 2295 if (cell == NULL) { | 1958 if (cell.is_null()) { |
| 2296 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 1959 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2297 | |
| 2298 STATIC_ASSERT(kSmiTag == 0); | 1960 STATIC_ASSERT(kSmiTag == 0); |
| 2299 __ JumpIfSmi(r1, &miss); | 1961 __ JumpIfSmi(r1, &miss); |
| 2300 | 1962 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
| 2301 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 1963 name, &miss); |
| 2302 &miss); | |
| 2303 } else { | 1964 } else { |
| 2304 ASSERT(cell->value() == function); | 1965 ASSERT(cell->value() == *function); |
| 2305 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1966 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1967 &miss); | |
| 2306 GenerateLoadFunctionFromCell(cell, function, &miss); | 1968 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2307 } | 1969 } |
| 2308 | 1970 |
| 2309 // Load the (only) argument into r0. | 1971 // Load the (only) argument into r0. |
| 2310 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 1972 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
| 2311 | 1973 |
| 2312 // If the argument is a smi, just return. | 1974 // If the argument is a smi, just return. |
| 2313 STATIC_ASSERT(kSmiTag == 0); | 1975 STATIC_ASSERT(kSmiTag == 0); |
| 2314 __ tst(r0, Operand(kSmiTagMask)); | 1976 __ tst(r0, Operand(kSmiTagMask)); |
| 2315 __ Drop(argc + 1, eq); | 1977 __ Drop(argc + 1, eq); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2397 // Restore FPCSR and fall to slow case. | 2059 // Restore FPCSR and fall to slow case. |
| 2398 __ vmsr(r3); | 2060 __ vmsr(r3); |
| 2399 | 2061 |
| 2400 __ bind(&slow); | 2062 __ bind(&slow); |
| 2401 // Tail call the full function. We do not have to patch the receiver | 2063 // Tail call the full function. We do not have to patch the receiver |
| 2402 // because the function makes no use of it. | 2064 // because the function makes no use of it. |
| 2403 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2065 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2404 | 2066 |
| 2405 __ bind(&miss); | 2067 __ bind(&miss); |
| 2406 // r2: function name. | 2068 // r2: function name. |
| 2407 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2069 GenerateMissBranch(); |
| 2408 if (maybe_result->IsFailure()) return maybe_result; | |
| 2409 | 2070 |
| 2410 // Return the generated code. | 2071 // Return the generated code. |
| 2411 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2072 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2412 } | 2073 } |
| 2413 | 2074 |
| 2414 | 2075 |
| 2415 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2076 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2416 JSObject* holder, | 2077 Handle<Object> object, |
| 2417 JSGlobalPropertyCell* cell, | 2078 Handle<JSObject> holder, |
| 2418 JSFunction* function, | 2079 Handle<JSGlobalPropertyCell> cell, |
| 2419 String* name) { | 2080 Handle<JSFunction> function, |
| 2081 Handle<String> name) { | |
| 2420 // ----------- S t a t e ------------- | 2082 // ----------- S t a t e ------------- |
| 2421 // -- r2 : function name | 2083 // -- r2 : function name |
| 2422 // -- lr : return address | 2084 // -- lr : return address |
| 2423 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2085 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2424 // -- ... | 2086 // -- ... |
| 2425 // -- sp[argc * 4] : receiver | 2087 // -- sp[argc * 4] : receiver |
| 2426 // ----------------------------------- | 2088 // ----------------------------------- |
| 2427 | 2089 |
| 2428 const int argc = arguments().immediate(); | 2090 const int argc = arguments().immediate(); |
| 2429 | |
| 2430 // If the object is not a JSObject or we got an unexpected number of | 2091 // If the object is not a JSObject or we got an unexpected number of |
| 2431 // arguments, bail out to the regular call. | 2092 // arguments, bail out to the regular call. |
| 2432 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2093 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2433 | 2094 |
| 2434 Label miss; | 2095 Label miss; |
| 2435 GenerateNameCheck(Handle<String>(name), &miss); | 2096 GenerateNameCheck(name, &miss); |
| 2436 | 2097 if (cell.is_null()) { |
| 2437 if (cell == NULL) { | |
| 2438 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2098 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2439 | |
| 2440 STATIC_ASSERT(kSmiTag == 0); | 2099 STATIC_ASSERT(kSmiTag == 0); |
| 2441 __ JumpIfSmi(r1, &miss); | 2100 __ JumpIfSmi(r1, &miss); |
| 2442 | 2101 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
| 2443 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2102 name, &miss); |
| 2444 &miss); | |
| 2445 } else { | 2103 } else { |
| 2446 ASSERT(cell->value() == function); | 2104 ASSERT(cell->value() == *function); |
| 2447 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 2105 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2106 &miss); | |
| 2448 GenerateLoadFunctionFromCell(cell, function, &miss); | 2107 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2449 } | 2108 } |
| 2450 | 2109 |
| 2451 // Load the (only) argument into r0. | 2110 // Load the (only) argument into r0. |
| 2452 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2111 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
| 2453 | 2112 |
| 2454 // Check if the argument is a smi. | 2113 // Check if the argument is a smi. |
| 2455 Label not_smi; | 2114 Label not_smi; |
| 2456 STATIC_ASSERT(kSmiTag == 0); | 2115 STATIC_ASSERT(kSmiTag == 0); |
| 2457 __ JumpIfNotSmi(r0, ¬_smi); | 2116 __ JumpIfNotSmi(r0, ¬_smi); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2498 __ Drop(argc + 1); | 2157 __ Drop(argc + 1); |
| 2499 __ Ret(); | 2158 __ Ret(); |
| 2500 | 2159 |
| 2501 // Tail call the full function. We do not have to patch the receiver | 2160 // Tail call the full function. We do not have to patch the receiver |
| 2502 // because the function makes no use of it. | 2161 // because the function makes no use of it. |
| 2503 __ bind(&slow); | 2162 __ bind(&slow); |
| 2504 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2163 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2505 | 2164 |
| 2506 __ bind(&miss); | 2165 __ bind(&miss); |
| 2507 // r2: function name. | 2166 // r2: function name. |
| 2508 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2167 GenerateMissBranch(); |
| 2509 if (maybe_result->IsFailure()) return maybe_result; | |
| 2510 | 2168 |
| 2511 // Return the generated code. | 2169 // Return the generated code. |
| 2512 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2170 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2513 } | 2171 } |
| 2514 | 2172 |
| 2515 | 2173 |
| 2516 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2174 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2517 const CallOptimization& optimization, | 2175 const CallOptimization& optimization, |
| 2518 Object* object, | 2176 Handle<Object> object, |
| 2519 JSObject* holder, | 2177 Handle<JSObject> holder, |
| 2520 JSGlobalPropertyCell* cell, | 2178 Handle<JSGlobalPropertyCell> cell, |
| 2521 JSFunction* function, | 2179 Handle<JSFunction> function, |
| 2522 String* name) { | 2180 Handle<String> name) { |
| 2523 Counters* counters = isolate()->counters(); | 2181 Counters* counters = isolate()->counters(); |
| 2524 | 2182 |
| 2525 ASSERT(optimization.is_simple_api_call()); | 2183 ASSERT(optimization.is_simple_api_call()); |
| 2526 // Bail out if object is a global object as we don't want to | 2184 // Bail out if object is a global object as we don't want to |
| 2527 // repatch it to global receiver. | 2185 // repatch it to global receiver. |
| 2528 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2186 if (object->IsGlobalObject()) return Handle<Code>::null(); |
| 2529 if (cell != NULL) return heap()->undefined_value(); | 2187 if (!cell.is_null()) return Handle<Code>::null(); |
| 2530 if (!object->IsJSObject()) return heap()->undefined_value(); | 2188 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 2531 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2189 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2532 JSObject::cast(object), holder); | 2190 Handle<JSObject>::cast(object), holder); |
| 2533 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2191 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); |
| 2534 | 2192 |
| 2535 Label miss, miss_before_stack_reserved; | 2193 Label miss, miss_before_stack_reserved; |
| 2536 | 2194 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2537 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); | |
| 2538 | 2195 |
| 2539 // Get the receiver from the stack. | 2196 // Get the receiver from the stack. |
| 2540 const int argc = arguments().immediate(); | 2197 const int argc = arguments().immediate(); |
| 2541 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2198 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2542 | 2199 |
| 2543 // Check that the receiver isn't a smi. | 2200 // Check that the receiver isn't a smi. |
| 2544 __ JumpIfSmi(r1, &miss_before_stack_reserved); | 2201 __ JumpIfSmi(r1, &miss_before_stack_reserved); |
| 2545 | 2202 |
| 2546 __ IncrementCounter(counters->call_const(), 1, r0, r3); | 2203 __ IncrementCounter(counters->call_const(), 1, r0, r3); |
| 2547 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); | 2204 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); |
| 2548 | 2205 |
| 2549 ReserveSpaceForFastApiCall(masm(), r0); | 2206 ReserveSpaceForFastApiCall(masm(), r0); |
| 2550 | 2207 |
| 2551 // Check that the maps haven't changed and find a Holder as a side effect. | 2208 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2552 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2209 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name, |
| 2553 depth, &miss); | 2210 depth, &miss); |
| 2554 | 2211 |
| 2555 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); | 2212 GenerateFastApiDirectCall(masm(), optimization, argc); |
| 2556 if (result->IsFailure()) return result; | |
| 2557 | 2213 |
| 2558 __ bind(&miss); | 2214 __ bind(&miss); |
| 2559 FreeSpaceForFastApiCall(masm()); | 2215 FreeSpaceForFastApiCall(masm()); |
| 2560 | 2216 |
| 2561 __ bind(&miss_before_stack_reserved); | 2217 __ bind(&miss_before_stack_reserved); |
| 2562 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2218 GenerateMissBranch(); |
| 2563 if (maybe_result->IsFailure()) return maybe_result; | |
| 2564 | 2219 |
| 2565 // Return the generated code. | 2220 // Return the generated code. |
| 2566 return TryGetCode(function); | 2221 return GetCode(function); |
| 2567 } | 2222 } |
| 2568 | 2223 |
| 2569 | 2224 |
| 2570 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2225 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, |
| 2571 JSObject* holder, | 2226 Handle<JSObject> holder, |
| 2572 JSFunction* function, | 2227 Handle<JSFunction> function, |
| 2573 String* name, | 2228 Handle<String> name, |
| 2574 CheckType check) { | 2229 CheckType check) { |
| 2575 // ----------- S t a t e ------------- | 2230 // ----------- S t a t e ------------- |
| 2576 // -- r2 : name | 2231 // -- r2 : name |
| 2577 // -- lr : return address | 2232 // -- lr : return address |
| 2578 // ----------------------------------- | 2233 // ----------------------------------- |
| 2579 if (HasCustomCallGenerator(function)) { | 2234 if (HasCustomCallGenerator(function)) { |
| 2580 MaybeObject* maybe_result = CompileCustomCall( | 2235 Handle<Code> code = CompileCustomCall(object, holder, |
| 2581 object, holder, NULL, function, name); | 2236 Handle<JSGlobalPropertyCell>::null(), |
| 2582 Object* result; | 2237 function, name); |
| 2583 if (!maybe_result->ToObject(&result)) return maybe_result; | 2238 // A null handle means bail out to the regular compiler code below. |
| 2584 // undefined means bail out to regular compiler. | 2239 if (!code.is_null()) return code; |
| 2585 if (!result->IsUndefined()) return result; | |
| 2586 } | 2240 } |
| 2587 | 2241 |
| 2588 Label miss; | 2242 Label miss; |
| 2589 | 2243 GenerateNameCheck(name, &miss); |
| 2590 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2591 | 2244 |
| 2592 // Get the receiver from the stack | 2245 // Get the receiver from the stack |
| 2593 const int argc = arguments().immediate(); | 2246 const int argc = arguments().immediate(); |
| 2594 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2247 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2595 | 2248 |
| 2596 // Check that the receiver isn't a smi. | 2249 // Check that the receiver isn't a smi. |
| 2597 if (check != NUMBER_CHECK) { | 2250 if (check != NUMBER_CHECK) { |
| 2598 __ JumpIfSmi(r1, &miss); | 2251 __ JumpIfSmi(r1, &miss); |
| 2599 } | 2252 } |
| 2600 | 2253 |
| 2601 // Make sure that it's okay not to patch the on stack receiver | 2254 // Make sure that it's okay not to patch the on stack receiver |
| 2602 // unless we're doing a receiver map check. | 2255 // unless we're doing a receiver map check. |
| 2603 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2256 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2604 | |
| 2605 SharedFunctionInfo* function_info = function->shared(); | |
| 2606 switch (check) { | 2257 switch (check) { |
| 2607 case RECEIVER_MAP_CHECK: | 2258 case RECEIVER_MAP_CHECK: |
| 2608 __ IncrementCounter(masm()->isolate()->counters()->call_const(), | 2259 __ IncrementCounter(masm()->isolate()->counters()->call_const(), |
| 2609 1, r0, r3); | 2260 1, r0, r3); |
| 2610 | 2261 |
| 2611 // Check that the maps haven't changed. | 2262 // Check that the maps haven't changed. |
| 2612 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2263 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
| 2613 &miss); | 2264 name, &miss); |
| 2614 | 2265 |
| 2615 // Patch the receiver on the stack with the global proxy if | 2266 // Patch the receiver on the stack with the global proxy if |
| 2616 // necessary. | 2267 // necessary. |
| 2617 if (object->IsGlobalObject()) { | 2268 if (object->IsGlobalObject()) { |
| 2618 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2269 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2619 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2270 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
| 2620 } | 2271 } |
| 2621 break; | 2272 break; |
| 2622 | 2273 |
| 2623 case STRING_CHECK: | 2274 case STRING_CHECK: |
| 2624 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2275 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2625 // Calling non-strict non-builtins with a value as the receiver | |
| 2626 // requires boxing. | |
| 2627 __ jmp(&miss); | |
| 2628 } else { | |
| 2629 // Check that the object is a two-byte string or a symbol. | 2276 // Check that the object is a two-byte string or a symbol. |
| 2630 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 2277 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
| 2631 __ b(ge, &miss); | 2278 __ b(ge, &miss); |
| 2632 // Check that the maps starting from the prototype haven't changed. | 2279 // Check that the maps starting from the prototype haven't changed. |
| 2633 GenerateDirectLoadGlobalFunctionPrototype( | 2280 GenerateDirectLoadGlobalFunctionPrototype( |
| 2634 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); | 2281 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); |
| 2635 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2282 CheckPrototypes( |
| 2636 r1, r4, name, &miss); | 2283 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2284 r0, holder, r3, r1, r4, name, &miss); | |
| 2285 } else { | |
| 2286 // Calling non-strict non-builtins with a value as the receiver | |
| 2287 // requires boxing. | |
| 2288 __ jmp(&miss); | |
| 2637 } | 2289 } |
| 2638 break; | 2290 break; |
| 2639 | 2291 |
| 2640 case NUMBER_CHECK: { | 2292 case NUMBER_CHECK: |
| 2641 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2293 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2642 // Calling non-strict non-builtins with a value as the receiver | |
| 2643 // requires boxing. | |
| 2644 __ jmp(&miss); | |
| 2645 } else { | |
| 2646 Label fast; | 2294 Label fast; |
| 2647 // Check that the object is a smi or a heap number. | 2295 // Check that the object is a smi or a heap number. |
| 2648 __ JumpIfSmi(r1, &fast); | 2296 __ JumpIfSmi(r1, &fast); |
| 2649 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2297 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
| 2650 __ b(ne, &miss); | 2298 __ b(ne, &miss); |
| 2651 __ bind(&fast); | 2299 __ bind(&fast); |
| 2652 // Check that the maps starting from the prototype haven't changed. | 2300 // Check that the maps starting from the prototype haven't changed. |
| 2653 GenerateDirectLoadGlobalFunctionPrototype( | 2301 GenerateDirectLoadGlobalFunctionPrototype( |
| 2654 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2302 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); |
| 2655 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2303 CheckPrototypes( |
| 2656 r1, r4, name, &miss); | 2304 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2657 } | 2305 r0, holder, r3, r1, r4, name, &miss); |
| 2658 break; | 2306 } else { |
| 2659 } | |
| 2660 | |
| 2661 case BOOLEAN_CHECK: { | |
| 2662 if (!function->IsBuiltin() && !function_info->strict_mode()) { | |
| 2663 // Calling non-strict non-builtins with a value as the receiver | 2307 // Calling non-strict non-builtins with a value as the receiver |
| 2664 // requires boxing. | 2308 // requires boxing. |
| 2665 __ jmp(&miss); | 2309 __ jmp(&miss); |
| 2666 } else { | 2310 } |
| 2311 break; | |
| 2312 | |
| 2313 case BOOLEAN_CHECK: | |
| 2314 if (function->IsBuiltin() || function->shared()->strict_mode()) { | |
| 2667 Label fast; | 2315 Label fast; |
| 2668 // Check that the object is a boolean. | 2316 // Check that the object is a boolean. |
| 2669 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2317 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 2670 __ cmp(r1, ip); | 2318 __ cmp(r1, ip); |
| 2671 __ b(eq, &fast); | 2319 __ b(eq, &fast); |
| 2672 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2320 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 2673 __ cmp(r1, ip); | 2321 __ cmp(r1, ip); |
| 2674 __ b(ne, &miss); | 2322 __ b(ne, &miss); |
| 2675 __ bind(&fast); | 2323 __ bind(&fast); |
| 2676 // Check that the maps starting from the prototype haven't changed. | 2324 // Check that the maps starting from the prototype haven't changed. |
| 2677 GenerateDirectLoadGlobalFunctionPrototype( | 2325 GenerateDirectLoadGlobalFunctionPrototype( |
| 2678 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); | 2326 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); |
| 2679 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2327 CheckPrototypes( |
| 2680 r1, r4, name, &miss); | 2328 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2329 r0, holder, r3, r1, r4, name, &miss); | |
| 2330 } else { | |
| 2331 // Calling non-strict non-builtins with a value as the receiver | |
| 2332 // requires boxing. | |
| 2333 __ jmp(&miss); | |
| 2681 } | 2334 } |
| 2682 break; | 2335 break; |
| 2683 } | |
| 2684 | |
| 2685 default: | |
| 2686 UNREACHABLE(); | |
|
ulan
2011/10/27 10:10:26
Wouldn't it be helpful in future if CheckType is e
Kevin Millikin (Chromium)
2011/10/27 10:53:43
Actually the opposite.
default: UNREACHABLE() can
| |
| 2687 } | 2336 } |
| 2688 | 2337 |
| 2689 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2338 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2690 ? CALL_AS_FUNCTION | 2339 ? CALL_AS_FUNCTION |
| 2691 : CALL_AS_METHOD; | 2340 : CALL_AS_METHOD; |
| 2692 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); | 2341 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); |
| 2693 | 2342 |
| 2694 // Handle call cache miss. | 2343 // Handle call cache miss. |
| 2695 __ bind(&miss); | 2344 __ bind(&miss); |
| 2696 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2345 GenerateMissBranch(); |
| 2697 if (maybe_result->IsFailure()) return maybe_result; | |
| 2698 | 2346 |
| 2699 // Return the generated code. | 2347 // Return the generated code. |
| 2700 return TryGetCode(function); | 2348 return GetCode(function); |
| 2701 } | 2349 } |
| 2702 | 2350 |
| 2703 | 2351 |
| 2704 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2352 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2705 JSObject* holder, | 2353 Handle<JSObject> holder, |
| 2706 String* name) { | 2354 Handle<String> name) { |
| 2707 // ----------- S t a t e ------------- | 2355 // ----------- S t a t e ------------- |
| 2708 // -- r2 : name | 2356 // -- r2 : name |
| 2709 // -- lr : return address | 2357 // -- lr : return address |
| 2710 // ----------------------------------- | 2358 // ----------------------------------- |
| 2711 | |
| 2712 Label miss; | 2359 Label miss; |
| 2713 | 2360 GenerateNameCheck(name, &miss); |
| 2714 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2715 | 2361 |
| 2716 // Get the number of arguments. | 2362 // Get the number of arguments. |
| 2717 const int argc = arguments().immediate(); | 2363 const int argc = arguments().immediate(); |
| 2718 | |
| 2719 LookupResult lookup(isolate()); | 2364 LookupResult lookup(isolate()); |
| 2720 LookupPostInterceptor(holder, name, &lookup); | 2365 LookupPostInterceptor(holder, name, &lookup); |
| 2721 | 2366 |
| 2722 // Get the receiver from the stack. | 2367 // Get the receiver from the stack. |
| 2723 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2368 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2724 | 2369 |
| 2725 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); | 2370 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); |
| 2726 MaybeObject* result = compiler.Compile(masm(), | 2371 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, |
| 2727 object, | 2372 &miss); |
| 2728 holder, | |
| 2729 name, | |
| 2730 &lookup, | |
| 2731 r1, | |
| 2732 r3, | |
| 2733 r4, | |
| 2734 r0, | |
| 2735 &miss); | |
| 2736 if (result->IsFailure()) { | |
| 2737 return result; | |
| 2738 } | |
| 2739 | 2373 |
| 2740 // Move returned value, the function to call, to r1. | 2374 // Move returned value, the function to call, to r1. |
| 2741 __ mov(r1, r0); | 2375 __ mov(r1, r0); |
| 2742 // Restore receiver. | 2376 // Restore receiver. |
| 2743 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2377 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 2744 | 2378 |
| 2745 GenerateCallFunction(masm(), Handle<Object>(object), arguments(), &miss, | 2379 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
| 2746 extra_state_); | |
| 2747 | 2380 |
| 2748 // Handle call cache miss. | 2381 // Handle call cache miss. |
| 2749 __ bind(&miss); | 2382 __ bind(&miss); |
| 2750 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2383 GenerateMissBranch(); |
| 2751 if (maybe_result->IsFailure()) return maybe_result; | |
| 2752 | 2384 |
| 2753 // Return the generated code. | 2385 // Return the generated code. |
| 2754 return TryGetCode(INTERCEPTOR, name); | 2386 return GetCode(INTERCEPTOR, name); |
| 2755 } | 2387 } |
| 2756 | 2388 |
| 2757 | 2389 |
| 2758 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2390 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2759 GlobalObject* holder, | 2391 Handle<JSObject> object, |
| 2760 JSGlobalPropertyCell* cell, | 2392 Handle<GlobalObject> holder, |
| 2761 JSFunction* function, | 2393 Handle<JSGlobalPropertyCell> cell, |
| 2762 String* name) { | 2394 Handle<JSFunction> function, |
| 2395 Handle<String> name) { | |
| 2763 // ----------- S t a t e ------------- | 2396 // ----------- S t a t e ------------- |
| 2764 // -- r2 : name | 2397 // -- r2 : name |
| 2765 // -- lr : return address | 2398 // -- lr : return address |
| 2766 // ----------------------------------- | 2399 // ----------------------------------- |
| 2767 | |
| 2768 if (HasCustomCallGenerator(function)) { | 2400 if (HasCustomCallGenerator(function)) { |
| 2769 MaybeObject* maybe_result = CompileCustomCall( | 2401 Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); |
| 2770 object, holder, cell, function, name); | 2402 // A null handle means bail out to the regular compiler code below. |
| 2771 Object* result; | 2403 if (!code.is_null()) return code; |
| 2772 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 2773 // undefined means bail out to regular compiler. | |
| 2774 if (!result->IsUndefined()) return result; | |
| 2775 } | 2404 } |
| 2776 | 2405 |
| 2777 Label miss; | 2406 Label miss; |
| 2778 | 2407 GenerateNameCheck(name, &miss); |
| 2779 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2780 | 2408 |
| 2781 // Get the number of arguments. | 2409 // Get the number of arguments. |
| 2782 const int argc = arguments().immediate(); | 2410 const int argc = arguments().immediate(); |
| 2783 | |
| 2784 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2411 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2785 | |
| 2786 GenerateLoadFunctionFromCell(cell, function, &miss); | 2412 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2787 | 2413 |
| 2788 // Patch the receiver on the stack with the global proxy if | 2414 // Patch the receiver on the stack with the global proxy if |
| 2789 // necessary. | 2415 // necessary. |
| 2790 if (object->IsGlobalObject()) { | 2416 if (object->IsGlobalObject()) { |
| 2791 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 2417 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
| 2792 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2418 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
| 2793 } | 2419 } |
| 2794 | 2420 |
| 2795 // Setup the context (function already in r1). | 2421 // Setup the context (function already in r1). |
| 2796 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 2422 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 2797 | 2423 |
| 2798 // Jump to the cached code (tail call). | 2424 // Jump to the cached code (tail call). |
| 2799 Counters* counters = masm()->isolate()->counters(); | 2425 Counters* counters = masm()->isolate()->counters(); |
| 2800 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2426 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
| 2801 Handle<Code> code(function->code()); | |
| 2802 ParameterCount expected(function->shared()->formal_parameter_count()); | 2427 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2803 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2428 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2804 ? CALL_AS_FUNCTION | 2429 ? CALL_AS_FUNCTION |
| 2805 : CALL_AS_METHOD; | 2430 : CALL_AS_METHOD; |
| 2806 // We call indirectly through the code field in the function to | 2431 // We call indirectly through the code field in the function to |
| 2807 // allow recompilation to take effect without changing any of the | 2432 // allow recompilation to take effect without changing any of the |
| 2808 // call sites. | 2433 // call sites. |
| 2809 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 2434 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 2810 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, | 2435 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, |
| 2811 NullCallWrapper(), call_kind); | 2436 NullCallWrapper(), call_kind); |
| 2812 | 2437 |
| 2813 // Handle call cache miss. | 2438 // Handle call cache miss. |
| 2814 __ bind(&miss); | 2439 __ bind(&miss); |
| 2815 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); | 2440 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); |
| 2816 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2441 GenerateMissBranch(); |
| 2817 if (maybe_result->IsFailure()) return maybe_result; | |
| 2818 | 2442 |
| 2819 // Return the generated code. | 2443 // Return the generated code. |
| 2820 return TryGetCode(NORMAL, name); | 2444 return GetCode(NORMAL, name); |
| 2821 } | 2445 } |
| 2822 | 2446 |
| 2823 | 2447 |
| 2824 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 2448 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2825 int index, | 2449 int index, |
| 2826 Handle<Map> transition, | 2450 Handle<Map> transition, |
| 2827 Handle<String> name) { | 2451 Handle<String> name) { |
| 2828 // ----------- S t a t e ------------- | 2452 // ----------- S t a t e ------------- |
| 2829 // -- r0 : value | 2453 // -- r0 : value |
| 2830 // -- r1 : receiver | 2454 // -- r1 : receiver |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3043 | 2667 |
| 3044 GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); | 2668 GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); |
| 3045 __ bind(&miss); | 2669 __ bind(&miss); |
| 3046 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2670 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3047 | 2671 |
| 3048 // Return the generated code. | 2672 // Return the generated code. |
| 3049 return GetCode(FIELD, name); | 2673 return GetCode(FIELD, name); |
| 3050 } | 2674 } |
| 3051 | 2675 |
| 3052 | 2676 |
| 3053 MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, | 2677 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 3054 JSObject* object, | 2678 Handle<String> name, |
| 3055 JSObject* holder, | 2679 Handle<JSObject> object, |
| 3056 AccessorInfo* callback) { | 2680 Handle<JSObject> holder, |
| 2681 Handle<AccessorInfo> callback) { | |
| 3057 // ----------- S t a t e ------------- | 2682 // ----------- S t a t e ------------- |
| 3058 // -- r0 : receiver | 2683 // -- r0 : receiver |
| 3059 // -- r2 : name | 2684 // -- r2 : name |
| 3060 // -- lr : return address | 2685 // -- lr : return address |
| 3061 // ----------------------------------- | 2686 // ----------------------------------- |
| 3062 Label miss; | 2687 Label miss; |
| 3063 | 2688 GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name, |
| 3064 MaybeObject* result = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, | 2689 &miss); |
| 3065 callback, name, &miss); | |
| 3066 if (result->IsFailure()) { | |
| 3067 miss.Unuse(); | |
| 3068 return result; | |
| 3069 } | |
| 3070 | |
| 3071 __ bind(&miss); | 2690 __ bind(&miss); |
| 3072 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2691 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3073 | 2692 |
| 3074 // Return the generated code. | 2693 // Return the generated code. |
| 3075 return TryGetCode(CALLBACKS, name); | 2694 return GetCode(CALLBACKS, name); |
| 3076 } | 2695 } |
| 3077 | 2696 |
| 3078 | 2697 |
| 3079 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, | 2698 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 3080 Handle<JSObject> holder, | 2699 Handle<JSObject> holder, |
| 3081 Handle<Object> value, | 2700 Handle<Object> value, |
| 3082 Handle<String> name) { | 2701 Handle<String> name) { |
| 3083 // ----------- S t a t e ------------- | 2702 // ----------- S t a t e ------------- |
| 3084 // -- r0 : receiver | 2703 // -- r0 : receiver |
| 3085 // -- r2 : name | 2704 // -- r2 : name |
| 3086 // -- lr : return address | 2705 // -- lr : return address |
| 3087 // ----------------------------------- | 2706 // ----------------------------------- |
| 3088 Label miss; | 2707 Label miss; |
| 3089 | 2708 |
| 3090 GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); | 2709 GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); |
| 3091 __ bind(&miss); | 2710 __ bind(&miss); |
| 3092 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2711 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3093 | 2712 |
| 3094 // Return the generated code. | 2713 // Return the generated code. |
| 3095 return GetCode(CONSTANT_FUNCTION, name); | 2714 return GetCode(CONSTANT_FUNCTION, name); |
| 3096 } | 2715 } |
| 3097 | 2716 |
| 3098 | 2717 |
| 3099 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, | 2718 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, |
| 3100 JSObject* holder, | 2719 Handle<JSObject> holder, |
| 3101 String* name) { | 2720 Handle<String> name) { |
| 3102 // ----------- S t a t e ------------- | 2721 // ----------- S t a t e ------------- |
| 3103 // -- r0 : receiver | 2722 // -- r0 : receiver |
| 3104 // -- r2 : name | 2723 // -- r2 : name |
| 3105 // -- lr : return address | 2724 // -- lr : return address |
| 3106 // ----------------------------------- | 2725 // ----------------------------------- |
| 3107 Label miss; | 2726 Label miss; |
| 3108 | 2727 |
| 3109 LookupResult lookup(isolate()); | 2728 LookupResult lookup(isolate()); |
| 3110 LookupPostInterceptor(holder, name, &lookup); | 2729 LookupPostInterceptor(holder, name, &lookup); |
| 3111 GenerateLoadInterceptor(object, | 2730 GenerateLoadInterceptor(object, holder, &lookup, r0, r2, r3, r1, r4, name, |
| 3112 holder, | |
| 3113 &lookup, | |
| 3114 r0, | |
| 3115 r2, | |
| 3116 r3, | |
| 3117 r1, | |
| 3118 r4, | |
| 3119 name, | |
| 3120 &miss); | 2731 &miss); |
| 3121 __ bind(&miss); | 2732 __ bind(&miss); |
| 3122 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2733 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3123 | 2734 |
| 3124 // Return the generated code. | 2735 // Return the generated code. |
| 3125 return TryGetCode(INTERCEPTOR, name); | 2736 return GetCode(INTERCEPTOR, name); |
| 3126 } | 2737 } |
| 3127 | 2738 |
| 3128 | 2739 |
| 3129 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2740 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3130 Handle<JSObject> object, | 2741 Handle<JSObject> object, |
| 3131 Handle<GlobalObject> holder, | 2742 Handle<GlobalObject> holder, |
| 3132 Handle<JSGlobalPropertyCell> cell, | 2743 Handle<JSGlobalPropertyCell> cell, |
| 3133 Handle<String> name, | 2744 Handle<String> name, |
| 3134 bool is_dont_delete) { | 2745 bool is_dont_delete) { |
| 3135 // ----------- S t a t e ------------- | 2746 // ----------- S t a t e ------------- |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3190 __ b(ne, &miss); | 2801 __ b(ne, &miss); |
| 3191 | 2802 |
| 3192 GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); | 2803 GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); |
| 3193 __ bind(&miss); | 2804 __ bind(&miss); |
| 3194 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2805 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3195 | 2806 |
| 3196 return GetCode(FIELD, name); | 2807 return GetCode(FIELD, name); |
| 3197 } | 2808 } |
| 3198 | 2809 |
| 3199 | 2810 |
| 3200 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2811 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
| 3201 String* name, | 2812 Handle<String> name, |
| 3202 JSObject* receiver, | 2813 Handle<JSObject> receiver, |
| 3203 JSObject* holder, | 2814 Handle<JSObject> holder, |
| 3204 AccessorInfo* callback) { | 2815 Handle<AccessorInfo> callback) { |
| 3205 // ----------- S t a t e ------------- | 2816 // ----------- S t a t e ------------- |
| 3206 // -- lr : return address | 2817 // -- lr : return address |
| 3207 // -- r0 : key | 2818 // -- r0 : key |
| 3208 // -- r1 : receiver | 2819 // -- r1 : receiver |
| 3209 // ----------------------------------- | 2820 // ----------------------------------- |
| 3210 Label miss; | 2821 Label miss; |
| 3211 | 2822 |
| 3212 // Check the key is the cached one. | 2823 // Check the key is the cached one. |
| 3213 __ cmp(r0, Operand(Handle<String>(name))); | 2824 __ cmp(r0, Operand(name)); |
| 3214 __ b(ne, &miss); | 2825 __ b(ne, &miss); |
| 3215 | 2826 |
| 3216 MaybeObject* result = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, | 2827 GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name, |
| 3217 r4, callback, name, &miss); | 2828 &miss); |
| 3218 if (result->IsFailure()) { | |
| 3219 miss.Unuse(); | |
| 3220 return result; | |
| 3221 } | |
| 3222 | |
| 3223 __ bind(&miss); | 2829 __ bind(&miss); |
| 3224 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2830 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3225 | 2831 |
| 3226 return TryGetCode(CALLBACKS, name); | 2832 return GetCode(CALLBACKS, name); |
| 3227 } | 2833 } |
| 3228 | 2834 |
| 3229 | 2835 |
| 3230 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( | 2836 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 3231 Handle<String> name, | 2837 Handle<String> name, |
| 3232 Handle<JSObject> receiver, | 2838 Handle<JSObject> receiver, |
| 3233 Handle<JSObject> holder, | 2839 Handle<JSObject> holder, |
| 3234 Handle<Object> value) { | 2840 Handle<Object> value) { |
| 3235 // ----------- S t a t e ------------- | 2841 // ----------- S t a t e ------------- |
| 3236 // -- lr : return address | 2842 // -- lr : return address |
| 3237 // -- r0 : key | 2843 // -- r0 : key |
| 3238 // -- r1 : receiver | 2844 // -- r1 : receiver |
| 3239 // ----------------------------------- | 2845 // ----------------------------------- |
| 3240 Label miss; | 2846 Label miss; |
| 3241 | 2847 |
| 3242 // Check the key is the cached one. | 2848 // Check the key is the cached one. |
| 3243 __ cmp(r0, Operand(name)); | 2849 __ cmp(r0, Operand(name)); |
| 3244 __ b(ne, &miss); | 2850 __ b(ne, &miss); |
| 3245 | 2851 |
| 3246 GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); | 2852 GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); |
| 3247 __ bind(&miss); | 2853 __ bind(&miss); |
| 3248 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2854 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3249 | 2855 |
| 3250 // Return the generated code. | 2856 // Return the generated code. |
| 3251 return GetCode(CONSTANT_FUNCTION, name); | 2857 return GetCode(CONSTANT_FUNCTION, name); |
| 3252 } | 2858 } |
| 3253 | 2859 |
| 3254 | 2860 |
| 3255 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2861 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
| 3256 JSObject* holder, | 2862 Handle<JSObject> receiver, |
| 3257 String* name) { | 2863 Handle<JSObject> holder, |
| 2864 Handle<String> name) { | |
| 3258 // ----------- S t a t e ------------- | 2865 // ----------- S t a t e ------------- |
| 3259 // -- lr : return address | 2866 // -- lr : return address |
| 3260 // -- r0 : key | 2867 // -- r0 : key |
| 3261 // -- r1 : receiver | 2868 // -- r1 : receiver |
| 3262 // ----------------------------------- | 2869 // ----------------------------------- |
| 3263 Label miss; | 2870 Label miss; |
| 3264 | 2871 |
| 3265 // Check the key is the cached one. | 2872 // Check the key is the cached one. |
| 3266 __ cmp(r0, Operand(Handle<String>(name))); | 2873 __ cmp(r0, Operand(name)); |
| 3267 __ b(ne, &miss); | 2874 __ b(ne, &miss); |
| 3268 | 2875 |
| 3269 LookupResult lookup(isolate()); | 2876 LookupResult lookup(isolate()); |
| 3270 LookupPostInterceptor(holder, name, &lookup); | 2877 LookupPostInterceptor(holder, name, &lookup); |
| 3271 GenerateLoadInterceptor(receiver, | 2878 GenerateLoadInterceptor(receiver, holder, &lookup, r1, r0, r2, r3, r4, name, |
| 3272 holder, | |
| 3273 &lookup, | |
| 3274 r1, | |
| 3275 r0, | |
| 3276 r2, | |
| 3277 r3, | |
| 3278 r4, | |
| 3279 name, | |
| 3280 &miss); | 2879 &miss); |
| 3281 __ bind(&miss); | 2880 __ bind(&miss); |
| 3282 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2881 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3283 | 2882 |
| 3284 return TryGetCode(INTERCEPTOR, name); | 2883 return GetCode(INTERCEPTOR, name); |
| 3285 } | 2884 } |
| 3286 | 2885 |
| 3287 | 2886 |
| 3288 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( | 2887 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3289 Handle<String> name) { | 2888 Handle<String> name) { |
| 3290 // ----------- S t a t e ------------- | 2889 // ----------- S t a t e ------------- |
| 3291 // -- lr : return address | 2890 // -- lr : return address |
| 3292 // -- r0 : key | 2891 // -- r0 : key |
| 3293 // -- r1 : receiver | 2892 // -- r1 : receiver |
| 3294 // ----------------------------------- | 2893 // ----------------------------------- |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4036 // -- lr : return address | 3635 // -- lr : return address |
| 4037 // -- r0 : key | 3636 // -- r0 : key |
| 4038 // -- r1 : receiver | 3637 // -- r1 : receiver |
| 4039 // ----------------------------------- | 3638 // ----------------------------------- |
| 4040 | 3639 |
| 4041 __ Push(r1, r0); | 3640 __ Push(r1, r0); |
| 4042 | 3641 |
| 4043 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3642 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 4044 | 3643 |
| 4045 __ bind(&miss_force_generic); | 3644 __ bind(&miss_force_generic); |
| 4046 Code* stub = masm->isolate()->builtins()->builtin( | 3645 Handle<Code> stub = |
| 4047 Builtins::kKeyedLoadIC_MissForceGeneric); | 3646 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 4048 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 3647 __ Jump(stub, RelocInfo::CODE_TARGET); |
| 4049 } | 3648 } |
| 4050 | 3649 |
| 4051 | 3650 |
| 4052 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3651 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
| 4053 MacroAssembler* masm, | 3652 MacroAssembler* masm, |
| 4054 ElementsKind elements_kind) { | 3653 ElementsKind elements_kind) { |
| 4055 // ---------- S t a t e -------------- | 3654 // ---------- S t a t e -------------- |
| 4056 // -- r0 : value | 3655 // -- r0 : value |
| 4057 // -- r1 : key | 3656 // -- r1 : key |
| 4058 // -- r2 : receiver | 3657 // -- r2 : receiver |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4412 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 4011 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4413 __ ldr(r4, | 4012 __ ldr(r4, |
| 4414 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4013 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4415 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 4014 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 4416 __ cmp(r4, ip); | 4015 __ cmp(r4, ip); |
| 4417 __ b(eq, &miss_force_generic); | 4016 __ b(eq, &miss_force_generic); |
| 4418 __ mov(r0, r4); | 4017 __ mov(r0, r4); |
| 4419 __ Ret(); | 4018 __ Ret(); |
| 4420 | 4019 |
| 4421 __ bind(&miss_force_generic); | 4020 __ bind(&miss_force_generic); |
| 4422 Code* stub = masm->isolate()->builtins()->builtin( | 4021 Handle<Code> stub = |
| 4423 Builtins::kKeyedLoadIC_MissForceGeneric); | 4022 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 4424 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 4023 __ Jump(stub, RelocInfo::CODE_TARGET); |
| 4425 } | 4024 } |
| 4426 | 4025 |
| 4427 | 4026 |
| 4428 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | 4027 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( |
| 4429 MacroAssembler* masm) { | 4028 MacroAssembler* masm) { |
| 4430 // ----------- S t a t e ------------- | 4029 // ----------- S t a t e ------------- |
| 4431 // -- lr : return address | 4030 // -- lr : return address |
| 4432 // -- r0 : key | 4031 // -- r0 : key |
| 4433 // -- r1 : receiver | 4032 // -- r1 : receiver |
| 4434 // ----------------------------------- | 4033 // ----------------------------------- |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4646 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4245 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4647 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | 4246 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
| 4648 } | 4247 } |
| 4649 | 4248 |
| 4650 | 4249 |
| 4651 #undef __ | 4250 #undef __ |
| 4652 | 4251 |
| 4653 } } // namespace v8::internal | 4252 } } // namespace v8::internal |
| 4654 | 4253 |
| 4655 #endif // V8_TARGET_ARCH_ARM | 4254 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |