| 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 __ pop(offset); | 100 __ pop(offset); |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 // Helper function used to check that the dictionary doesn't contain | 105 // Helper function used to check that the dictionary doesn't contain |
| 106 // the property. This function may return false negatives, so miss_label | 106 // the property. This function may return false negatives, so miss_label |
| 107 // must always call a backup property check that is complete. | 107 // must always call a backup property check that is complete. |
| 108 // This function is safe to call if the receiver has fast properties. | 108 // This function is safe to call if the receiver has fast properties. |
| 109 // Name must be a symbol and receiver must be a heap object. | 109 // Name must be a symbol and receiver must be a heap object. |
| 110 static MaybeObject* GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 111 Label* miss_label, | 111 Label* miss_label, |
| 112 Register receiver, | 112 Register receiver, |
| 113 String* name, | 113 Handle<String> name, |
| 114 Register r0, | 114 Register r0, |
| 115 Register r1) { | 115 Register r1) { |
| 116 ASSERT(name->IsSymbol()); | 116 ASSERT(name->IsSymbol()); |
| 117 Counters* counters = masm->isolate()->counters(); | 117 Counters* counters = masm->isolate()->counters(); |
| 118 __ IncrementCounter(counters->negative_lookups(), 1); | 118 __ IncrementCounter(counters->negative_lookups(), 1); |
| 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 120 | 120 |
| 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 122 | 122 |
| 123 const int kInterceptorOrAccessCheckNeededMask = | 123 const int kInterceptorOrAccessCheckNeededMask = |
| 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 125 | 125 |
| 126 // Bail out if the receiver has a named interceptor or requires access checks. | 126 // Bail out if the receiver has a named interceptor or requires access checks. |
| 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 128 kInterceptorOrAccessCheckNeededMask); | 128 kInterceptorOrAccessCheckNeededMask); |
| 129 __ j(not_zero, miss_label); | 129 __ j(not_zero, miss_label); |
| 130 | 130 |
| 131 // Check that receiver is a JSObject. | 131 // Check that receiver is a JSObject. |
| 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); | 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 133 __ j(below, miss_label); | 133 __ j(below, miss_label); |
| 134 | 134 |
| 135 // Load properties array. | 135 // Load properties array. |
| 136 Register properties = r0; | 136 Register properties = r0; |
| 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 138 | 138 |
| 139 // Check that the properties array is a dictionary. | 139 // Check that the properties array is a dictionary. |
| 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 141 Immediate(masm->isolate()->factory()->hash_table_map())); | 141 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 142 __ j(not_equal, miss_label); | 142 __ j(not_equal, miss_label); |
| 143 | 143 |
| 144 Label done; | 144 Label done; |
| 145 StringDictionaryLookupStub::GenerateNegativeLookup(masm, |
| 146 miss_label, |
| 147 &done, |
| 148 properties, |
| 149 name, |
| 150 r1); |
| 151 __ bind(&done); |
| 152 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 153 } |
| 154 |
| 155 |
| 156 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 157 // handlified. |
| 158 static MaybeObject* TryGenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 159 Label* miss_label, |
| 160 Register receiver, |
| 161 String* name, |
| 162 Register r0, |
| 163 Register r1) { |
| 164 ASSERT(name->IsSymbol()); |
| 165 Counters* counters = masm->isolate()->counters(); |
| 166 __ IncrementCounter(counters->negative_lookups(), 1); |
| 167 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 168 |
| 169 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 170 |
| 171 const int kInterceptorOrAccessCheckNeededMask = |
| 172 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 173 |
| 174 // Bail out if the receiver has a named interceptor or requires access checks. |
| 175 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 176 kInterceptorOrAccessCheckNeededMask); |
| 177 __ j(not_zero, miss_label); |
| 178 |
| 179 // Check that receiver is a JSObject. |
| 180 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 181 __ j(below, miss_label); |
| 182 |
| 183 // Load properties array. |
| 184 Register properties = r0; |
| 185 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 186 |
| 187 // Check that the properties array is a dictionary. |
| 188 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 189 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 190 __ j(not_equal, miss_label); |
| 191 |
| 192 Label done; |
| 145 MaybeObject* result = | 193 MaybeObject* result = |
| 146 StringDictionaryLookupStub::GenerateNegativeLookup(masm, | 194 StringDictionaryLookupStub::TryGenerateNegativeLookup(masm, |
| 147 miss_label, | 195 miss_label, |
| 148 &done, | 196 &done, |
| 149 properties, | 197 properties, |
| 150 name, | 198 name, |
| 151 r1); | 199 r1); |
| 152 if (result->IsFailure()) return result; | 200 if (result->IsFailure()) return result; |
| 153 | 201 |
| 154 __ bind(&done); | 202 __ bind(&done); |
| 155 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 203 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 156 | 204 |
| 157 return result; | 205 return result; |
| 158 } | 206 } |
| 159 | 207 |
| 160 | 208 |
| 161 void StubCache::GenerateProbe(MacroAssembler* masm, | 209 void StubCache::GenerateProbe(MacroAssembler* masm, |
| 162 Code::Flags flags, | 210 Code::Flags flags, |
| 163 Register receiver, | 211 Register receiver, |
| 164 Register name, | 212 Register name, |
| 165 Register scratch, | 213 Register scratch, |
| 166 Register extra, | 214 Register extra, |
| 167 Register extra2) { | 215 Register extra2) { |
| 168 Isolate* isolate = Isolate::Current(); | |
| 169 Label miss; | 216 Label miss; |
| 170 USE(extra2); // The register extra2 is not used on the ia32 platform. | |
| 171 | 217 |
| 172 // Make sure that code is valid. The shifting code relies on the | 218 // Assert that code is valid. The shifting code relies on the entry size |
| 173 // entry size being 8. | 219 // being 8. |
| 174 ASSERT(sizeof(Entry) == 8); | 220 ASSERT(sizeof(Entry) == 8); |
| 175 | 221 |
| 176 // Make sure the flags does not name a specific type. | 222 // Assert the flags do not name a specific type. |
| 177 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 223 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
| 178 | 224 |
| 179 // Make sure that there are no register conflicts. | 225 // Assert that there are no register conflicts. |
| 180 ASSERT(!scratch.is(receiver)); | 226 ASSERT(!scratch.is(receiver)); |
| 181 ASSERT(!scratch.is(name)); | 227 ASSERT(!scratch.is(name)); |
| 182 ASSERT(!extra.is(receiver)); | 228 ASSERT(!extra.is(receiver)); |
| 183 ASSERT(!extra.is(name)); | 229 ASSERT(!extra.is(name)); |
| 184 ASSERT(!extra.is(scratch)); | 230 ASSERT(!extra.is(scratch)); |
| 185 | 231 |
| 186 // Check scratch and extra registers are valid, and extra2 is unused. | 232 // Assert scratch and extra registers are valid, and extra2 is unused. |
| 187 ASSERT(!scratch.is(no_reg)); | 233 ASSERT(!scratch.is(no_reg)); |
| 188 ASSERT(extra2.is(no_reg)); | 234 ASSERT(extra2.is(no_reg)); |
| 189 | 235 |
| 190 // Check that the receiver isn't a smi. | 236 // Check that the receiver isn't a smi. |
| 191 __ JumpIfSmi(receiver, &miss); | 237 __ JumpIfSmi(receiver, &miss); |
| 192 | 238 |
| 193 // Get the map of the receiver and compute the hash. | 239 // Get the map of the receiver and compute the hash. |
| 194 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 240 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
| 195 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 241 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 196 __ xor_(scratch, flags); | 242 __ xor_(scratch, flags); |
| 197 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 243 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
| 198 | 244 |
| 199 // Probe the primary table. | 245 // Probe the primary table. |
| 200 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 246 ProbeTable(isolate(), masm, flags, kPrimary, name, scratch, extra); |
| 201 | 247 |
| 202 // Primary miss: Compute hash for secondary probe. | 248 // Primary miss: Compute hash for secondary probe. |
| 203 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 249 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
| 204 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 250 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 205 __ xor_(scratch, flags); | 251 __ xor_(scratch, flags); |
| 206 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 252 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
| 207 __ sub(scratch, name); | 253 __ sub(scratch, name); |
| 208 __ add(scratch, Immediate(flags)); | 254 __ add(scratch, Immediate(flags)); |
| 209 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); | 255 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); |
| 210 | 256 |
| 211 // Probe the secondary table. | 257 // Probe the secondary table. |
| 212 ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra); | 258 ProbeTable(isolate(), masm, flags, kSecondary, name, scratch, extra); |
| 213 | 259 |
| 214 // Cache miss: Fall-through and let caller handle the miss by | 260 // Cache miss: Fall-through and let caller handle the miss by |
| 215 // entering the runtime system. | 261 // entering the runtime system. |
| 216 __ bind(&miss); | 262 __ bind(&miss); |
| 217 } | 263 } |
| 218 | 264 |
| 219 | 265 |
| 220 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 266 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
| 221 int index, | 267 int index, |
| 222 Register prototype) { | 268 Register prototype) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 321 __ mov(eax, scratch1); | 367 __ mov(eax, scratch1); |
| 322 __ ret(0); | 368 __ ret(0); |
| 323 } | 369 } |
| 324 | 370 |
| 325 | 371 |
| 326 // Load a fast property out of a holder object (src). In-object properties | 372 // Load a fast property out of a holder object (src). In-object properties |
| 327 // are loaded directly otherwise the property is loaded from the properties | 373 // are loaded directly otherwise the property is loaded from the properties |
| 328 // fixed array. | 374 // fixed array. |
| 329 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 330 Register dst, Register src, | 376 Register dst, |
| 331 JSObject* holder, int index) { | 377 Register src, |
| 378 Handle<JSObject> holder, |
| 379 int index) { |
| 332 // Adjust for the number of properties stored in the holder. | 380 // Adjust for the number of properties stored in the holder. |
| 333 index -= holder->map()->inobject_properties(); | 381 index -= holder->map()->inobject_properties(); |
| 334 if (index < 0) { | 382 if (index < 0) { |
| 335 // Get the property straight out of the holder. | 383 // Get the property straight out of the holder. |
| 336 int offset = holder->map()->instance_size() + (index * kPointerSize); | 384 int offset = holder->map()->instance_size() + (index * kPointerSize); |
| 337 __ mov(dst, FieldOperand(src, offset)); | 385 __ mov(dst, FieldOperand(src, offset)); |
| 338 } else { | 386 } else { |
| 339 // Calculate the offset into the properties array. | 387 // Calculate the offset into the properties array. |
| 340 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 388 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 341 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 389 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 return masm->TryCallApiFunctionAndReturn(&fun, | 527 return masm->TryCallApiFunctionAndReturn(&fun, |
| 480 argc + kFastApiCallArguments + 1); | 528 argc + kFastApiCallArguments + 1); |
| 481 } | 529 } |
| 482 | 530 |
| 483 | 531 |
| 484 class CallInterceptorCompiler BASE_EMBEDDED { | 532 class CallInterceptorCompiler BASE_EMBEDDED { |
| 485 public: | 533 public: |
| 486 CallInterceptorCompiler(StubCompiler* stub_compiler, | 534 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 487 const ParameterCount& arguments, | 535 const ParameterCount& arguments, |
| 488 Register name, | 536 Register name, |
| 489 Code::ExtraICState extra_ic_state) | 537 Code::ExtraICState extra_state) |
| 490 : stub_compiler_(stub_compiler), | 538 : stub_compiler_(stub_compiler), |
| 491 arguments_(arguments), | 539 arguments_(arguments), |
| 492 name_(name), | 540 name_(name), |
| 493 extra_ic_state_(extra_ic_state) {} | 541 extra_state_(extra_state) {} |
| 494 | 542 |
| 495 MaybeObject* Compile(MacroAssembler* masm, | 543 MaybeObject* Compile(MacroAssembler* masm, |
| 496 JSObject* object, | 544 JSObject* object, |
| 497 JSObject* holder, | 545 JSObject* holder, |
| 498 String* name, | 546 String* name, |
| 499 LookupResult* lookup, | 547 LookupResult* lookup, |
| 500 Register receiver, | 548 Register receiver, |
| 501 Register scratch1, | 549 Register scratch1, |
| 502 Register scratch2, | 550 Register scratch2, |
| 503 Register scratch3, | 551 Register scratch3, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 // by the previous CheckPrototypes. | 655 // by the previous CheckPrototypes. |
| 608 ASSERT(depth2 == kInvalidProtoDepth); | 656 ASSERT(depth2 == kInvalidProtoDepth); |
| 609 } | 657 } |
| 610 | 658 |
| 611 // Invoke function. | 659 // Invoke function. |
| 612 if (can_do_fast_api_call) { | 660 if (can_do_fast_api_call) { |
| 613 MaybeObject* result = | 661 MaybeObject* result = |
| 614 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 662 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 615 if (result->IsFailure()) return result; | 663 if (result->IsFailure()) return result; |
| 616 } else { | 664 } else { |
| 617 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 665 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 618 ? CALL_AS_FUNCTION | 666 ? CALL_AS_FUNCTION |
| 619 : CALL_AS_METHOD; | 667 : CALL_AS_METHOD; |
| 620 __ InvokeFunction(optimization.constant_function(), arguments_, | 668 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 621 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 669 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 622 } | 670 } |
| 623 | 671 |
| 624 // Deferred code for fast API call case---clean preallocated space. | 672 // Deferred code for fast API call case---clean preallocated space. |
| 625 if (can_do_fast_api_call) { | 673 if (can_do_fast_api_call) { |
| 626 __ bind(&miss_cleanup); | 674 __ bind(&miss_cleanup); |
| 627 FreeSpaceForFastApiCall(masm, scratch1); | 675 FreeSpaceForFastApiCall(masm, scratch1); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 // Leave the internal frame. | 741 // Leave the internal frame. |
| 694 } | 742 } |
| 695 | 743 |
| 696 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); | 744 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); |
| 697 __ j(not_equal, interceptor_succeeded); | 745 __ j(not_equal, interceptor_succeeded); |
| 698 } | 746 } |
| 699 | 747 |
| 700 StubCompiler* stub_compiler_; | 748 StubCompiler* stub_compiler_; |
| 701 const ParameterCount& arguments_; | 749 const ParameterCount& arguments_; |
| 702 Register name_; | 750 Register name_; |
| 703 Code::ExtraICState extra_ic_state_; | 751 Code::ExtraICState extra_state_; |
| 704 }; | 752 }; |
| 705 | 753 |
| 706 | 754 |
| 707 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 755 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| 708 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 756 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
| 709 Code* code = NULL; | 757 Handle<Code> code = (kind == Code::LOAD_IC) |
| 710 if (kind == Code::LOAD_IC) { | 758 ? masm->isolate()->builtins()->LoadIC_Miss() |
| 711 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); | 759 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); |
| 712 } else { | 760 __ jmp(code, RelocInfo::CODE_TARGET); |
| 713 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); | |
| 714 } | |
| 715 | |
| 716 Handle<Code> ic(code); | |
| 717 __ jmp(ic, RelocInfo::CODE_TARGET); | |
| 718 } | 761 } |
| 719 | 762 |
| 720 | 763 |
| 721 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | 764 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
| 722 Code* code = masm->isolate()->builtins()->builtin( | 765 Code* code = masm->isolate()->builtins()->builtin( |
| 723 Builtins::kKeyedLoadIC_MissForceGeneric); | 766 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 724 Handle<Code> ic(code); | 767 Handle<Code> ic(code); |
| 725 __ jmp(ic, RelocInfo::CODE_TARGET); | 768 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 726 } | 769 } |
| 727 | 770 |
| 728 | 771 |
| 729 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 772 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 730 // but may be destroyed if store is successful. | 773 // but may be destroyed if store is successful. |
| 731 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 774 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 732 JSObject* object, | 775 Handle<JSObject> object, |
| 733 int index, | 776 int index, |
| 734 Map* transition, | 777 Handle<Map> transition, |
| 735 Register receiver_reg, | 778 Register receiver_reg, |
| 736 Register name_reg, | 779 Register name_reg, |
| 737 Register scratch, | 780 Register scratch, |
| 738 Label* miss_label) { | 781 Label* miss_label) { |
| 739 // Check that the object isn't a smi. | 782 // Check that the object isn't a smi. |
| 740 __ JumpIfSmi(receiver_reg, miss_label); | 783 __ JumpIfSmi(receiver_reg, miss_label); |
| 741 | 784 |
| 742 // Check that the map of the object hasn't changed. | 785 // Check that the map of the object hasn't changed. |
| 743 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 786 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 744 Immediate(Handle<Map>(object->map()))); | 787 Immediate(Handle<Map>(object->map()))); |
| 745 __ j(not_equal, miss_label); | 788 __ j(not_equal, miss_label); |
| 746 | 789 |
| 747 // Perform global security token check if needed. | 790 // Perform global security token check if needed. |
| 748 if (object->IsJSGlobalProxy()) { | 791 if (object->IsJSGlobalProxy()) { |
| 749 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 792 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 750 } | 793 } |
| 751 | 794 |
| 752 // Stub never generated for non-global objects that require access | 795 // Stub never generated for non-global objects that require access |
| 753 // checks. | 796 // checks. |
| 754 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 797 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 755 | 798 |
| 756 // Perform map transition for the receiver if necessary. | 799 // Perform map transition for the receiver if necessary. |
| 757 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { | 800 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
| 758 // The properties must be extended before we can store the value. | 801 // The properties must be extended before we can store the value. |
| 759 // We jump to a runtime call that extends the properties array. | 802 // We jump to a runtime call that extends the properties array. |
| 760 __ pop(scratch); // Return address. | 803 __ pop(scratch); // Return address. |
| 761 __ push(receiver_reg); | 804 __ push(receiver_reg); |
| 762 __ push(Immediate(Handle<Map>(transition))); | 805 __ push(Immediate(transition)); |
| 763 __ push(eax); | 806 __ push(eax); |
| 764 __ push(scratch); | 807 __ push(scratch); |
| 765 __ TailCallExternalReference( | 808 __ TailCallExternalReference( |
| 766 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 809 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 767 masm->isolate()), | 810 masm->isolate()), |
| 768 3, | 811 3, |
| 769 1); | 812 1); |
| 770 return; | 813 return; |
| 771 } | 814 } |
| 772 | 815 |
| 773 if (transition != NULL) { | 816 if (!transition.is_null()) { |
| 774 // Update the map of the object; no write barrier updating is | 817 // Update the map of the object; no write barrier updating is |
| 775 // needed because the map is never in new space. | 818 // needed because the map is never in new space. |
| 776 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 819 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 777 Immediate(Handle<Map>(transition))); | 820 Immediate(transition)); |
| 778 } | 821 } |
| 779 | 822 |
| 780 // Adjust for the number of properties stored in the object. Even in the | 823 // Adjust for the number of properties stored in the object. Even in the |
| 781 // face of a transition we can use the old map here because the size of the | 824 // face of a transition we can use the old map here because the size of the |
| 782 // object and the number of in-object properties is not going to change. | 825 // object and the number of in-object properties is not going to change. |
| 783 index -= object->map()->inobject_properties(); | 826 index -= object->map()->inobject_properties(); |
| 784 | 827 |
| 785 if (index < 0) { | 828 if (index < 0) { |
| 786 // Set the property straight into the object. | 829 // Set the property straight into the object. |
| 787 int offset = object->map()->instance_size() + (index * kPointerSize); | 830 int offset = object->map()->instance_size() + (index * kPointerSize); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 813 } | 856 } |
| 814 | 857 |
| 815 // Return the value (register eax). | 858 // Return the value (register eax). |
| 816 __ ret(0); | 859 __ ret(0); |
| 817 } | 860 } |
| 818 | 861 |
| 819 | 862 |
| 820 // Generate code to check that a global property cell is empty. Create | 863 // Generate code to check that a global property cell is empty. Create |
| 821 // the property cell at compilation time if no cell exists for the | 864 // the property cell at compilation time if no cell exists for the |
| 822 // property. | 865 // property. |
| 823 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 866 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 867 Handle<GlobalObject> global, |
| 868 Handle<String> name, |
| 869 Register scratch, |
| 870 Label* miss) { |
| 871 Handle<JSGlobalPropertyCell> cell = |
| 872 GlobalObject::EnsurePropertyCell(global, name); |
| 873 ASSERT(cell->value()->IsTheHole()); |
| 874 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
| 875 if (Serializer::enabled()) { |
| 876 __ mov(scratch, Immediate(cell)); |
| 877 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 878 Immediate(the_hole)); |
| 879 } else { |
| 880 __ cmp(Operand::Cell(cell), Immediate(the_hole)); |
| 881 } |
| 882 __ j(not_equal, miss); |
| 883 } |
| 884 |
| 885 |
| 886 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 887 // handlified. |
| 888 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( |
| 824 MacroAssembler* masm, | 889 MacroAssembler* masm, |
| 825 GlobalObject* global, | 890 GlobalObject* global, |
| 826 String* name, | 891 String* name, |
| 827 Register scratch, | 892 Register scratch, |
| 828 Label* miss) { | 893 Label* miss) { |
| 829 Object* probe; | 894 Object* probe; |
| 830 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 895 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
| 831 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 896 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
| 832 } | 897 } |
| 833 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 898 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 834 ASSERT(cell->value()->IsTheHole()); | 899 ASSERT(cell->value()->IsTheHole()); |
| 835 if (Serializer::enabled()) { | 900 if (Serializer::enabled()) { |
| 836 __ mov(scratch, Immediate(Handle<Object>(cell))); | 901 __ mov(scratch, Immediate(Handle<Object>(cell))); |
| 837 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 902 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 838 Immediate(masm->isolate()->factory()->the_hole_value())); | 903 Immediate(masm->isolate()->factory()->the_hole_value())); |
| 839 } else { | 904 } else { |
| 840 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 905 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
| 841 Immediate(masm->isolate()->factory()->the_hole_value())); | 906 Immediate(masm->isolate()->factory()->the_hole_value())); |
| 842 } | 907 } |
| 843 __ j(not_equal, miss); | 908 __ j(not_equal, miss); |
| 844 return cell; | 909 return cell; |
| 845 } | 910 } |
| 846 | 911 |
| 847 | 912 |
| 848 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 913 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 849 // from object to (but not including) holder. | 914 // from object to (but not including) holder. |
| 850 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 915 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 916 Handle<JSObject> object, |
| 917 Handle<JSObject> holder, |
| 918 Handle<String> name, |
| 919 Register scratch, |
| 920 Label* miss) { |
| 921 Handle<JSObject> current = object; |
| 922 while (!current.is_identical_to(holder)) { |
| 923 if (current->IsGlobalObject()) { |
| 924 GenerateCheckPropertyCell(masm, |
| 925 Handle<GlobalObject>::cast(current), |
| 926 name, |
| 927 scratch, |
| 928 miss); |
| 929 } |
| 930 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 931 } |
| 932 } |
| 933 |
| 934 |
| 935 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 936 // handlified. |
| 937 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( |
| 851 MacroAssembler* masm, | 938 MacroAssembler* masm, |
| 852 JSObject* object, | 939 JSObject* object, |
| 853 JSObject* holder, | 940 JSObject* holder, |
| 854 String* name, | 941 String* name, |
| 855 Register scratch, | 942 Register scratch, |
| 856 Label* miss) { | 943 Label* miss) { |
| 857 JSObject* current = object; | 944 JSObject* current = object; |
| 858 while (current != holder) { | 945 while (current != holder) { |
| 859 if (current->IsGlobalObject()) { | 946 if (current->IsGlobalObject()) { |
| 860 // Returns a cell or a failure. | 947 // Returns a cell or a failure. |
| 861 MaybeObject* result = GenerateCheckPropertyCell( | 948 MaybeObject* result = TryGenerateCheckPropertyCell( |
| 862 masm, | 949 masm, |
| 863 GlobalObject::cast(current), | 950 GlobalObject::cast(current), |
| 864 name, | 951 name, |
| 865 scratch, | 952 scratch, |
| 866 miss); | 953 miss); |
| 867 if (result->IsFailure()) return result; | 954 if (result->IsFailure()) return result; |
| 868 } | 955 } |
| 869 ASSERT(current->IsJSObject()); | 956 ASSERT(current->IsJSObject()); |
| 870 current = JSObject::cast(current->GetPrototype()); | 957 current = JSObject::cast(current->GetPrototype()); |
| 871 } | 958 } |
| 872 return NULL; | 959 return NULL; |
| 873 } | 960 } |
| 874 | 961 |
| 875 | 962 |
| 876 #undef __ | 963 #undef __ |
| 877 #define __ ACCESS_MASM(masm()) | 964 #define __ ACCESS_MASM(masm()) |
| 878 | 965 |
| 879 | 966 |
| 967 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 968 Register object_reg, |
| 969 Handle<JSObject> holder, |
| 970 Register holder_reg, |
| 971 Register scratch1, |
| 972 Register scratch2, |
| 973 Handle<String> name, |
| 974 int save_at_depth, |
| 975 Label* miss) { |
| 976 // Make sure there's no overlap between holder and object registers. |
| 977 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 978 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 979 && !scratch2.is(scratch1)); |
| 980 |
| 981 // Keep track of the current object in register reg. |
| 982 Register reg = object_reg; |
| 983 Handle<JSObject> current = object; |
| 984 int depth = 0; |
| 985 |
| 986 if (save_at_depth == depth) { |
| 987 __ mov(Operand(esp, kPointerSize), reg); |
| 988 } |
| 989 |
| 990 // Traverse the prototype chain and check the maps in the prototype chain for |
| 991 // fast and global objects or do negative lookup for normal objects. |
| 992 while (!current.is_identical_to(holder)) { |
| 993 ++depth; |
| 994 |
| 995 // Only global objects and objects that do not require access |
| 996 // checks are allowed in stubs. |
| 997 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 998 |
| 999 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); |
| 1000 if (!current->HasFastProperties() && |
| 1001 !current->IsJSGlobalObject() && |
| 1002 !current->IsJSGlobalProxy()) { |
| 1003 if (!name->IsSymbol()) { |
| 1004 name = factory()->LookupSymbol(name); |
| 1005 } |
| 1006 ASSERT(current->property_dictionary()->FindEntry(*name) == |
| 1007 StringDictionary::kNotFound); |
| 1008 |
| 1009 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1010 scratch1, scratch2); |
| 1011 |
| 1012 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1013 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1014 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1015 } else { |
| 1016 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1017 Handle<Map> current_map(current->map()); |
| 1018 if (in_new_space) { |
| 1019 // Save the map in scratch1 for later. |
| 1020 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1021 __ cmp(scratch1, Immediate(current_map)); |
| 1022 } else { |
| 1023 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1024 Immediate(current_map)); |
| 1025 } |
| 1026 // Branch on the result of the map check. |
| 1027 __ j(not_equal, miss); |
| 1028 // Check access rights to the global object. This has to happen after |
| 1029 // the map check so that we know that the object is actually a global |
| 1030 // object. |
| 1031 if (current->IsJSGlobalProxy()) { |
| 1032 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1033 } |
| 1034 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1035 |
| 1036 if (in_new_space) { |
| 1037 // The prototype is in new space; we cannot store a reference to it |
| 1038 // in the code. Load it from the map. |
| 1039 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1040 } else { |
| 1041 // The prototype is in old space; load it directly. |
| 1042 __ mov(reg, prototype); |
| 1043 } |
| 1044 } |
| 1045 |
| 1046 if (save_at_depth == depth) { |
| 1047 __ mov(Operand(esp, kPointerSize), reg); |
| 1048 } |
| 1049 |
| 1050 // Go to the next object in the prototype chain. |
| 1051 current = prototype; |
| 1052 } |
| 1053 ASSERT(current.is_identical_to(holder)); |
| 1054 |
| 1055 // Log the check depth. |
| 1056 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1057 |
| 1058 // Check the holder map. |
| 1059 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1060 Immediate(Handle<Map>(holder->map()))); |
| 1061 __ j(not_equal, miss); |
| 1062 |
| 1063 // Perform security check for access to the global object. |
| 1064 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1065 if (holder->IsJSGlobalProxy()) { |
| 1066 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1067 } |
| 1068 |
| 1069 // If we've skipped any global objects, it's not enough to verify that |
| 1070 // their maps haven't changed. We also need to check that the property |
| 1071 // cell for the property is still empty. |
| 1072 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1073 |
| 1074 // Return the register containing the holder. |
| 1075 return reg; |
| 1076 } |
| 1077 |
| 1078 |
| 1079 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1080 // handlified. |
| 880 Register StubCompiler::CheckPrototypes(JSObject* object, | 1081 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 881 Register object_reg, | 1082 Register object_reg, |
| 882 JSObject* holder, | 1083 JSObject* holder, |
| 883 Register holder_reg, | 1084 Register holder_reg, |
| 884 Register scratch1, | 1085 Register scratch1, |
| 885 Register scratch2, | 1086 Register scratch2, |
| 886 String* name, | 1087 String* name, |
| 887 int save_at_depth, | 1088 int save_at_depth, |
| 888 Label* miss) { | 1089 Label* miss) { |
| 889 // Make sure there's no overlap between holder and object registers. | 1090 // Make sure there's no overlap between holder and object registers. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 919 Object* lookup_result = NULL; // Initialization to please compiler. | 1120 Object* lookup_result = NULL; // Initialization to please compiler. |
| 920 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 1121 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
| 921 set_failure(Failure::cast(maybe_lookup_result)); | 1122 set_failure(Failure::cast(maybe_lookup_result)); |
| 922 return reg; | 1123 return reg; |
| 923 } | 1124 } |
| 924 name = String::cast(lookup_result); | 1125 name = String::cast(lookup_result); |
| 925 } | 1126 } |
| 926 ASSERT(current->property_dictionary()->FindEntry(name) == | 1127 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 927 StringDictionary::kNotFound); | 1128 StringDictionary::kNotFound); |
| 928 | 1129 |
| 929 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1130 MaybeObject* negative_lookup = |
| 930 miss, | 1131 TryGenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 931 reg, | 1132 scratch1, scratch2); |
| 932 name, | |
| 933 scratch1, | |
| 934 scratch2); | |
| 935 if (negative_lookup->IsFailure()) { | 1133 if (negative_lookup->IsFailure()) { |
| 936 set_failure(Failure::cast(negative_lookup)); | 1134 set_failure(Failure::cast(negative_lookup)); |
| 937 return reg; | 1135 return reg; |
| 938 } | 1136 } |
| 939 | 1137 |
| 940 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1138 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 941 reg = holder_reg; // from now the object is in holder_reg | 1139 reg = holder_reg; // from now the object is in holder_reg |
| 942 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1140 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 943 } else if (heap()->InNewSpace(prototype)) { | 1141 } else if (heap()->InNewSpace(prototype)) { |
| 944 // Get the map of the current object. | 1142 // Get the map of the current object. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 | 1189 |
| 992 // Check the holder map. | 1190 // Check the holder map. |
| 993 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1191 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 994 Immediate(Handle<Map>(holder->map()))); | 1192 Immediate(Handle<Map>(holder->map()))); |
| 995 __ j(not_equal, miss); | 1193 __ j(not_equal, miss); |
| 996 | 1194 |
| 997 // Perform security check for access to the global object. | 1195 // Perform security check for access to the global object. |
| 998 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1196 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 999 if (holder->IsJSGlobalProxy()) { | 1197 if (holder->IsJSGlobalProxy()) { |
| 1000 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1198 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1001 }; | 1199 } |
| 1002 | 1200 |
| 1003 // If we've skipped any global objects, it's not enough to verify | 1201 // If we've skipped any global objects, it's not enough to verify |
| 1004 // that their maps haven't changed. We also need to check that the | 1202 // that their maps haven't changed. We also need to check that the |
| 1005 // property cell for the property is still empty. | 1203 // property cell for the property is still empty. |
| 1006 MaybeObject* result = GenerateCheckPropertyCells(masm(), | 1204 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
| 1007 object, | 1205 object, |
| 1008 holder, | 1206 holder, |
| 1009 name, | 1207 name, |
| 1010 scratch1, | 1208 scratch1, |
| 1011 miss); | 1209 miss); |
| 1012 if (result->IsFailure()) set_failure(Failure::cast(result)); | 1210 if (result->IsFailure()) set_failure(Failure::cast(result)); |
| 1013 | 1211 |
| 1014 // Return the register containing the holder. | 1212 // Return the register containing the holder. |
| 1015 return reg; | 1213 return reg; |
| 1016 } | 1214 } |
| 1017 | 1215 |
| 1018 | 1216 |
| 1019 void StubCompiler::GenerateLoadField(JSObject* object, | 1217 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
| 1020 JSObject* holder, | 1218 Handle<JSObject> holder, |
| 1021 Register receiver, | 1219 Register receiver, |
| 1022 Register scratch1, | 1220 Register scratch1, |
| 1023 Register scratch2, | 1221 Register scratch2, |
| 1024 Register scratch3, | 1222 Register scratch3, |
| 1025 int index, | 1223 int index, |
| 1026 String* name, | 1224 Handle<String> name, |
| 1027 Label* miss) { | 1225 Label* miss) { |
| 1028 // Check that the receiver isn't a smi. | 1226 // Check that the receiver isn't a smi. |
| 1029 __ JumpIfSmi(receiver, miss); | 1227 __ JumpIfSmi(receiver, miss); |
| 1030 | 1228 |
| 1031 // Check the prototype chain. | 1229 // Check the prototype chain. |
| 1032 Register reg = | 1230 Register reg = CheckPrototypes( |
| 1033 CheckPrototypes(object, receiver, holder, | 1231 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1034 scratch1, scratch2, scratch3, name, miss); | |
| 1035 | 1232 |
| 1036 // Get the value from the properties. | 1233 // Get the value from the properties. |
| 1037 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1234 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
| 1038 __ ret(0); | 1235 __ ret(0); |
| 1039 } | 1236 } |
| 1040 | 1237 |
| 1041 | 1238 |
| 1042 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1239 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1043 JSObject* holder, | 1240 JSObject* holder, |
| 1044 Register receiver, | 1241 Register receiver, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. | 1296 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. |
| 1100 | 1297 |
| 1101 // Emitting a stub call may try to allocate (if the code is not | 1298 // Emitting a stub call may try to allocate (if the code is not |
| 1102 // already generated). Do not allow the assembler to perform a | 1299 // already generated). Do not allow the assembler to perform a |
| 1103 // garbage collection but instead return the allocation failure | 1300 // garbage collection but instead return the allocation failure |
| 1104 // object. | 1301 // object. |
| 1105 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); | 1302 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); |
| 1106 } | 1303 } |
| 1107 | 1304 |
| 1108 | 1305 |
| 1109 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1306 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, |
| 1110 JSObject* holder, | 1307 Handle<JSObject> holder, |
| 1111 Register receiver, | 1308 Register receiver, |
| 1112 Register scratch1, | 1309 Register scratch1, |
| 1113 Register scratch2, | 1310 Register scratch2, |
| 1114 Register scratch3, | 1311 Register scratch3, |
| 1115 Object* value, | 1312 Handle<Object> value, |
| 1116 String* name, | 1313 Handle<String> name, |
| 1117 Label* miss) { | 1314 Label* miss) { |
| 1118 // Check that the receiver isn't a smi. | 1315 // Check that the receiver isn't a smi. |
| 1119 __ JumpIfSmi(receiver, miss); | 1316 __ JumpIfSmi(receiver, miss); |
| 1120 | 1317 |
| 1121 // Check that the maps haven't changed. | 1318 // Check that the maps haven't changed. |
| 1122 CheckPrototypes(object, receiver, holder, | 1319 CheckPrototypes( |
| 1123 scratch1, scratch2, scratch3, name, miss); | 1320 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
| 1124 | 1321 |
| 1125 // Return the constant value. | 1322 // Return the constant value. |
| 1126 __ mov(eax, Handle<Object>(value)); | 1323 __ mov(eax, value); |
| 1127 __ ret(0); | 1324 __ ret(0); |
| 1128 } | 1325 } |
| 1129 | 1326 |
| 1130 | 1327 |
| 1131 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1328 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
| 1132 JSObject* interceptor_holder, | 1329 JSObject* interceptor_holder, |
| 1133 LookupResult* lookup, | 1330 LookupResult* lookup, |
| 1134 Register receiver, | 1331 Register receiver, |
| 1135 Register name_reg, | 1332 Register name_reg, |
| 1136 Register scratch1, | 1333 Register scratch1, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 scratch2, | 1413 scratch2, |
| 1217 scratch3, | 1414 scratch3, |
| 1218 name, | 1415 name, |
| 1219 miss); | 1416 miss); |
| 1220 } | 1417 } |
| 1221 | 1418 |
| 1222 if (lookup->type() == FIELD) { | 1419 if (lookup->type() == FIELD) { |
| 1223 // We found FIELD property in prototype chain of interceptor's holder. | 1420 // We found FIELD property in prototype chain of interceptor's holder. |
| 1224 // Retrieve a field from field's holder. | 1421 // Retrieve a field from field's holder. |
| 1225 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1422 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
| 1226 lookup->holder(), lookup->GetFieldIndex()); | 1423 Handle<JSObject>(lookup->holder()), |
| 1424 lookup->GetFieldIndex()); |
| 1227 __ ret(0); | 1425 __ ret(0); |
| 1228 } else { | 1426 } else { |
| 1229 // We found CALLBACKS property in prototype chain of interceptor's | 1427 // We found CALLBACKS property in prototype chain of interceptor's |
| 1230 // holder. | 1428 // holder. |
| 1231 ASSERT(lookup->type() == CALLBACKS); | 1429 ASSERT(lookup->type() == CALLBACKS); |
| 1232 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1430 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
| 1233 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1431 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
| 1234 ASSERT(callback != NULL); | 1432 ASSERT(callback != NULL); |
| 1235 ASSERT(callback->getter() != NULL); | 1433 ASSERT(callback->getter() != NULL); |
| 1236 | 1434 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1263 __ push(scratch2); // restore old return address | 1461 __ push(scratch2); // restore old return address |
| 1264 | 1462 |
| 1265 ExternalReference ref = | 1463 ExternalReference ref = |
| 1266 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1464 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1267 isolate()); | 1465 isolate()); |
| 1268 __ TailCallExternalReference(ref, 5, 1); | 1466 __ TailCallExternalReference(ref, 5, 1); |
| 1269 } | 1467 } |
| 1270 } | 1468 } |
| 1271 | 1469 |
| 1272 | 1470 |
| 1273 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1471 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1274 if (kind_ == Code::KEYED_CALL_IC) { | 1472 if (kind_ == Code::KEYED_CALL_IC) { |
| 1275 __ cmp(ecx, Immediate(Handle<String>(name))); | 1473 __ cmp(ecx, Immediate(name)); |
| 1276 __ j(not_equal, miss); | 1474 __ j(not_equal, miss); |
| 1277 } | 1475 } |
| 1278 } | 1476 } |
| 1279 | 1477 |
| 1280 | 1478 |
| 1281 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1479 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1282 JSObject* holder, | 1480 JSObject* holder, |
| 1283 String* name, | 1481 String* name, |
| 1284 Label* miss) { | 1482 Label* miss) { |
| 1285 ASSERT(holder->IsGlobalObject()); | 1483 ASSERT(holder->IsGlobalObject()); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1328 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1526 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
| 1329 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1527 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
| 1330 __ j(not_equal, miss); | 1528 __ j(not_equal, miss); |
| 1331 } else { | 1529 } else { |
| 1332 __ cmp(edi, Immediate(Handle<JSFunction>(function))); | 1530 __ cmp(edi, Immediate(Handle<JSFunction>(function))); |
| 1333 __ j(not_equal, miss); | 1531 __ j(not_equal, miss); |
| 1334 } | 1532 } |
| 1335 } | 1533 } |
| 1336 | 1534 |
| 1337 | 1535 |
| 1338 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1536 void CallStubCompiler::GenerateMissBranch() { |
| 1339 MaybeObject* maybe_obj = | 1537 Handle<Code> code = |
| 1340 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1538 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1341 kind_, | 1539 kind_, |
| 1342 extra_ic_state_); | 1540 extra_state_); |
| 1541 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1542 } |
| 1543 |
| 1544 |
| 1545 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1546 // handlified. |
| 1547 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { |
| 1548 MaybeObject* maybe_obj = |
| 1549 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1550 kind_, |
| 1551 extra_state_); |
| 1343 Object* obj; | 1552 Object* obj; |
| 1344 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1553 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1345 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1554 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1346 return obj; | 1555 return obj; |
| 1347 } | 1556 } |
| 1348 | 1557 |
| 1349 | 1558 |
| 1350 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1559 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1351 JSObject* object, | 1560 Handle<JSObject> holder, |
| 1352 JSObject* holder, | 1561 int index, |
| 1353 int index, | 1562 Handle<String> name) { |
| 1354 String* name) { | |
| 1355 // ----------- S t a t e ------------- | 1563 // ----------- S t a t e ------------- |
| 1356 // -- ecx : name | 1564 // -- ecx : name |
| 1357 // -- esp[0] : return address | 1565 // -- esp[0] : return address |
| 1358 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1566 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1359 // -- ... | 1567 // -- ... |
| 1360 // -- esp[(argc + 1) * 4] : receiver | 1568 // -- esp[(argc + 1) * 4] : receiver |
| 1361 // ----------------------------------- | 1569 // ----------------------------------- |
| 1362 Label miss; | 1570 Label miss; |
| 1363 | 1571 |
| 1364 GenerateNameCheck(name, &miss); | 1572 GenerateNameCheck(name, &miss); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1382 __ j(not_equal, &miss); | 1590 __ j(not_equal, &miss); |
| 1383 | 1591 |
| 1384 // Patch the receiver on the stack with the global proxy if | 1592 // Patch the receiver on the stack with the global proxy if |
| 1385 // necessary. | 1593 // necessary. |
| 1386 if (object->IsGlobalObject()) { | 1594 if (object->IsGlobalObject()) { |
| 1387 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1595 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 1388 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1596 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 1389 } | 1597 } |
| 1390 | 1598 |
| 1391 // Invoke the function. | 1599 // Invoke the function. |
| 1392 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 1600 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1393 ? CALL_AS_FUNCTION | 1601 ? CALL_AS_FUNCTION |
| 1394 : CALL_AS_METHOD; | 1602 : CALL_AS_METHOD; |
| 1395 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 1603 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 1396 NullCallWrapper(), call_kind); | 1604 NullCallWrapper(), call_kind); |
| 1397 | 1605 |
| 1398 // Handle call cache miss. | 1606 // Handle call cache miss. |
| 1399 __ bind(&miss); | 1607 __ bind(&miss); |
| 1400 MaybeObject* maybe_result = GenerateMissBranch(); | 1608 GenerateMissBranch(); |
| 1401 if (maybe_result->IsFailure()) return maybe_result; | |
| 1402 | 1609 |
| 1403 // Return the generated code. | 1610 // Return the generated code. |
| 1404 return GetCode(FIELD, name); | 1611 return GetCode(FIELD, name); |
| 1405 } | 1612 } |
| 1406 | 1613 |
| 1407 | 1614 |
| 1408 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1615 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1409 JSObject* holder, | 1616 JSObject* holder, |
| 1410 JSGlobalPropertyCell* cell, | 1617 JSGlobalPropertyCell* cell, |
| 1411 JSFunction* function, | 1618 JSFunction* function, |
| 1412 String* name) { | 1619 String* name) { |
| 1413 // ----------- S t a t e ------------- | 1620 // ----------- S t a t e ------------- |
| 1414 // -- ecx : name | 1621 // -- ecx : name |
| 1415 // -- esp[0] : return address | 1622 // -- esp[0] : return address |
| 1416 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1623 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1417 // -- ... | 1624 // -- ... |
| 1418 // -- esp[(argc + 1) * 4] : receiver | 1625 // -- esp[(argc + 1) * 4] : receiver |
| 1419 // ----------------------------------- | 1626 // ----------------------------------- |
| 1420 | 1627 |
| 1421 // If object is not an array, bail out to regular call. | 1628 // If object is not an array, bail out to regular call. |
| 1422 if (!object->IsJSArray() || cell != NULL) { | 1629 if (!object->IsJSArray() || cell != NULL) { |
| 1423 return isolate()->heap()->undefined_value(); | 1630 return isolate()->heap()->undefined_value(); |
| 1424 } | 1631 } |
| 1425 | 1632 |
| 1426 Label miss; | 1633 Label miss; |
| 1427 | 1634 |
| 1428 GenerateNameCheck(name, &miss); | 1635 GenerateNameCheck(Handle<String>(name), &miss); |
| 1429 | 1636 |
| 1430 // Get the receiver from the stack. | 1637 // Get the receiver from the stack. |
| 1431 const int argc = arguments().immediate(); | 1638 const int argc = arguments().immediate(); |
| 1432 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1639 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1433 | 1640 |
| 1434 // Check that the receiver isn't a smi. | 1641 // Check that the receiver isn't a smi. |
| 1435 __ JumpIfSmi(edx, &miss); | 1642 __ JumpIfSmi(edx, &miss); |
| 1436 | 1643 |
| 1437 CheckPrototypes(JSObject::cast(object), edx, | 1644 CheckPrototypes(JSObject::cast(object), edx, |
| 1438 holder, ebx, | 1645 holder, ebx, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1506 __ bind(&attempt_to_grow_elements); | 1713 __ bind(&attempt_to_grow_elements); |
| 1507 if (!FLAG_inline_new) { | 1714 if (!FLAG_inline_new) { |
| 1508 __ jmp(&call_builtin); | 1715 __ jmp(&call_builtin); |
| 1509 } | 1716 } |
| 1510 | 1717 |
| 1511 __ mov(edi, Operand(esp, argc * kPointerSize)); | 1718 __ mov(edi, Operand(esp, argc * kPointerSize)); |
| 1512 // Growing elements that are SMI-only requires special handling in case | 1719 // Growing elements that are SMI-only requires special handling in case |
| 1513 // the new element is non-Smi. For now, delegate to the builtin. | 1720 // the new element is non-Smi. For now, delegate to the builtin. |
| 1514 Label no_fast_elements_check; | 1721 Label no_fast_elements_check; |
| 1515 __ JumpIfSmi(edi, &no_fast_elements_check); | 1722 __ JumpIfSmi(edi, &no_fast_elements_check); |
| 1516 __ mov(esi, FieldOperand(edx, HeapObject::kMapOffset)); | 1723 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 1517 __ CheckFastObjectElements(esi, &call_builtin, Label::kFar); | 1724 __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar); |
| 1518 __ bind(&no_fast_elements_check); | 1725 __ bind(&no_fast_elements_check); |
| 1519 | 1726 |
| 1520 // We could be lucky and the elements array could be at the top of | 1727 // We could be lucky and the elements array could be at the top of |
| 1521 // new-space. In this case we can just grow it in place by moving the | 1728 // new-space. In this case we can just grow it in place by moving the |
| 1522 // allocation pointer up. | 1729 // allocation pointer up. |
| 1523 | 1730 |
| 1524 ExternalReference new_space_allocation_top = | 1731 ExternalReference new_space_allocation_top = |
| 1525 ExternalReference::new_space_allocation_top_address(isolate()); | 1732 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1526 ExternalReference new_space_allocation_limit = | 1733 ExternalReference new_space_allocation_limit = |
| 1527 ExternalReference::new_space_allocation_limit_address(isolate()); | 1734 ExternalReference::new_space_allocation_limit_address(isolate()); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1575 } | 1782 } |
| 1576 | 1783 |
| 1577 __ bind(&call_builtin); | 1784 __ bind(&call_builtin); |
| 1578 __ TailCallExternalReference( | 1785 __ TailCallExternalReference( |
| 1579 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1786 ExternalReference(Builtins::c_ArrayPush, isolate()), |
| 1580 argc + 1, | 1787 argc + 1, |
| 1581 1); | 1788 1); |
| 1582 } | 1789 } |
| 1583 | 1790 |
| 1584 __ bind(&miss); | 1791 __ bind(&miss); |
| 1585 MaybeObject* maybe_result = GenerateMissBranch(); | 1792 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1586 if (maybe_result->IsFailure()) return maybe_result; | 1793 if (maybe_result->IsFailure()) return maybe_result; |
| 1587 | 1794 |
| 1588 // Return the generated code. | 1795 // Return the generated code. |
| 1589 return GetCode(function); | 1796 return TryGetCode(function); |
| 1590 } | 1797 } |
| 1591 | 1798 |
| 1592 | 1799 |
| 1593 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1800 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1594 JSObject* holder, | 1801 JSObject* holder, |
| 1595 JSGlobalPropertyCell* cell, | 1802 JSGlobalPropertyCell* cell, |
| 1596 JSFunction* function, | 1803 JSFunction* function, |
| 1597 String* name) { | 1804 String* name) { |
| 1598 // ----------- S t a t e ------------- | 1805 // ----------- S t a t e ------------- |
| 1599 // -- ecx : name | 1806 // -- ecx : name |
| 1600 // -- esp[0] : return address | 1807 // -- esp[0] : return address |
| 1601 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1808 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1602 // -- ... | 1809 // -- ... |
| 1603 // -- esp[(argc + 1) * 4] : receiver | 1810 // -- esp[(argc + 1) * 4] : receiver |
| 1604 // ----------------------------------- | 1811 // ----------------------------------- |
| 1605 | 1812 |
| 1606 // If object is not an array, bail out to regular call. | 1813 // If object is not an array, bail out to regular call. |
| 1607 if (!object->IsJSArray() || cell != NULL) { | 1814 if (!object->IsJSArray() || cell != NULL) { |
| 1608 return heap()->undefined_value(); | 1815 return heap()->undefined_value(); |
| 1609 } | 1816 } |
| 1610 | 1817 |
| 1611 Label miss, return_undefined, call_builtin; | 1818 Label miss, return_undefined, call_builtin; |
| 1612 | 1819 |
| 1613 GenerateNameCheck(name, &miss); | 1820 GenerateNameCheck(Handle<String>(name), &miss); |
| 1614 | 1821 |
| 1615 // Get the receiver from the stack. | 1822 // Get the receiver from the stack. |
| 1616 const int argc = arguments().immediate(); | 1823 const int argc = arguments().immediate(); |
| 1617 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1824 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1618 | 1825 |
| 1619 // Check that the receiver isn't a smi. | 1826 // Check that the receiver isn't a smi. |
| 1620 __ JumpIfSmi(edx, &miss); | 1827 __ JumpIfSmi(edx, &miss); |
| 1621 CheckPrototypes(JSObject::cast(object), edx, | 1828 CheckPrototypes(JSObject::cast(object), edx, |
| 1622 holder, ebx, | 1829 holder, ebx, |
| 1623 eax, edi, name, &miss); | 1830 eax, edi, name, &miss); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1658 __ mov(eax, Immediate(factory()->undefined_value())); | 1865 __ mov(eax, Immediate(factory()->undefined_value())); |
| 1659 __ ret((argc + 1) * kPointerSize); | 1866 __ ret((argc + 1) * kPointerSize); |
| 1660 | 1867 |
| 1661 __ bind(&call_builtin); | 1868 __ bind(&call_builtin); |
| 1662 __ TailCallExternalReference( | 1869 __ TailCallExternalReference( |
| 1663 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1870 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 1664 argc + 1, | 1871 argc + 1, |
| 1665 1); | 1872 1); |
| 1666 | 1873 |
| 1667 __ bind(&miss); | 1874 __ bind(&miss); |
| 1668 MaybeObject* maybe_result = GenerateMissBranch(); | 1875 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1669 if (maybe_result->IsFailure()) return maybe_result; | 1876 if (maybe_result->IsFailure()) return maybe_result; |
| 1670 | 1877 |
| 1671 // Return the generated code. | 1878 // Return the generated code. |
| 1672 return GetCode(function); | 1879 return TryGetCode(function); |
| 1673 } | 1880 } |
| 1674 | 1881 |
| 1675 | 1882 |
| 1676 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1883 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1677 Object* object, | 1884 Object* object, |
| 1678 JSObject* holder, | 1885 JSObject* holder, |
| 1679 JSGlobalPropertyCell* cell, | 1886 JSGlobalPropertyCell* cell, |
| 1680 JSFunction* function, | 1887 JSFunction* function, |
| 1681 String* name) { | 1888 String* name) { |
| 1682 // ----------- S t a t e ------------- | 1889 // ----------- S t a t e ------------- |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1693 } | 1900 } |
| 1694 | 1901 |
| 1695 const int argc = arguments().immediate(); | 1902 const int argc = arguments().immediate(); |
| 1696 | 1903 |
| 1697 Label miss; | 1904 Label miss; |
| 1698 Label name_miss; | 1905 Label name_miss; |
| 1699 Label index_out_of_range; | 1906 Label index_out_of_range; |
| 1700 Label* index_out_of_range_label = &index_out_of_range; | 1907 Label* index_out_of_range_label = &index_out_of_range; |
| 1701 | 1908 |
| 1702 if (kind_ == Code::CALL_IC && | 1909 if (kind_ == Code::CALL_IC && |
| 1703 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1910 (CallICBase::StringStubState::decode(extra_state_) == |
| 1704 DEFAULT_STRING_STUB)) { | 1911 DEFAULT_STRING_STUB)) { |
| 1705 index_out_of_range_label = &miss; | 1912 index_out_of_range_label = &miss; |
| 1706 } | 1913 } |
| 1707 | 1914 |
| 1708 GenerateNameCheck(name, &name_miss); | 1915 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1709 | 1916 |
| 1710 // Check that the maps starting from the prototype haven't changed. | 1917 // Check that the maps starting from the prototype haven't changed. |
| 1711 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1918 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1712 Context::STRING_FUNCTION_INDEX, | 1919 Context::STRING_FUNCTION_INDEX, |
| 1713 eax, | 1920 eax, |
| 1714 &miss); | 1921 &miss); |
| 1715 ASSERT(object != holder); | 1922 ASSERT(object != holder); |
| 1716 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1923 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1717 ebx, edx, edi, name, &miss); | 1924 ebx, edx, edi, name, &miss); |
| 1718 | 1925 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1744 if (index_out_of_range.is_linked()) { | 1951 if (index_out_of_range.is_linked()) { |
| 1745 __ bind(&index_out_of_range); | 1952 __ bind(&index_out_of_range); |
| 1746 __ Set(eax, Immediate(factory()->nan_value())); | 1953 __ Set(eax, Immediate(factory()->nan_value())); |
| 1747 __ ret((argc + 1) * kPointerSize); | 1954 __ ret((argc + 1) * kPointerSize); |
| 1748 } | 1955 } |
| 1749 | 1956 |
| 1750 __ bind(&miss); | 1957 __ bind(&miss); |
| 1751 // Restore function name in ecx. | 1958 // Restore function name in ecx. |
| 1752 __ Set(ecx, Immediate(Handle<String>(name))); | 1959 __ Set(ecx, Immediate(Handle<String>(name))); |
| 1753 __ bind(&name_miss); | 1960 __ bind(&name_miss); |
| 1754 MaybeObject* maybe_result = GenerateMissBranch(); | 1961 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1755 if (maybe_result->IsFailure()) return maybe_result; | 1962 if (maybe_result->IsFailure()) return maybe_result; |
| 1756 | 1963 |
| 1757 // Return the generated code. | 1964 // Return the generated code. |
| 1758 return GetCode(function); | 1965 return TryGetCode(function); |
| 1759 } | 1966 } |
| 1760 | 1967 |
| 1761 | 1968 |
| 1762 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1969 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
| 1763 Object* object, | 1970 Object* object, |
| 1764 JSObject* holder, | 1971 JSObject* holder, |
| 1765 JSGlobalPropertyCell* cell, | 1972 JSGlobalPropertyCell* cell, |
| 1766 JSFunction* function, | 1973 JSFunction* function, |
| 1767 String* name) { | 1974 String* name) { |
| 1768 // ----------- S t a t e ------------- | 1975 // ----------- S t a t e ------------- |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1779 } | 1986 } |
| 1780 | 1987 |
| 1781 const int argc = arguments().immediate(); | 1988 const int argc = arguments().immediate(); |
| 1782 | 1989 |
| 1783 Label miss; | 1990 Label miss; |
| 1784 Label name_miss; | 1991 Label name_miss; |
| 1785 Label index_out_of_range; | 1992 Label index_out_of_range; |
| 1786 Label* index_out_of_range_label = &index_out_of_range; | 1993 Label* index_out_of_range_label = &index_out_of_range; |
| 1787 | 1994 |
| 1788 if (kind_ == Code::CALL_IC && | 1995 if (kind_ == Code::CALL_IC && |
| 1789 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1996 (CallICBase::StringStubState::decode(extra_state_) == |
| 1790 DEFAULT_STRING_STUB)) { | 1997 DEFAULT_STRING_STUB)) { |
| 1791 index_out_of_range_label = &miss; | 1998 index_out_of_range_label = &miss; |
| 1792 } | 1999 } |
| 1793 | 2000 |
| 1794 GenerateNameCheck(name, &name_miss); | 2001 GenerateNameCheck(Handle<String>(name), &name_miss); |
| 1795 | 2002 |
| 1796 // Check that the maps starting from the prototype haven't changed. | 2003 // Check that the maps starting from the prototype haven't changed. |
| 1797 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2004 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1798 Context::STRING_FUNCTION_INDEX, | 2005 Context::STRING_FUNCTION_INDEX, |
| 1799 eax, | 2006 eax, |
| 1800 &miss); | 2007 &miss); |
| 1801 ASSERT(object != holder); | 2008 ASSERT(object != holder); |
| 1802 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2009 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 1803 ebx, edx, edi, name, &miss); | 2010 ebx, edx, edi, name, &miss); |
| 1804 | 2011 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1832 if (index_out_of_range.is_linked()) { | 2039 if (index_out_of_range.is_linked()) { |
| 1833 __ bind(&index_out_of_range); | 2040 __ bind(&index_out_of_range); |
| 1834 __ Set(eax, Immediate(factory()->empty_string())); | 2041 __ Set(eax, Immediate(factory()->empty_string())); |
| 1835 __ ret((argc + 1) * kPointerSize); | 2042 __ ret((argc + 1) * kPointerSize); |
| 1836 } | 2043 } |
| 1837 | 2044 |
| 1838 __ bind(&miss); | 2045 __ bind(&miss); |
| 1839 // Restore function name in ecx. | 2046 // Restore function name in ecx. |
| 1840 __ Set(ecx, Immediate(Handle<String>(name))); | 2047 __ Set(ecx, Immediate(Handle<String>(name))); |
| 1841 __ bind(&name_miss); | 2048 __ bind(&name_miss); |
| 1842 MaybeObject* maybe_result = GenerateMissBranch(); | 2049 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1843 if (maybe_result->IsFailure()) return maybe_result; | 2050 if (maybe_result->IsFailure()) return maybe_result; |
| 1844 | 2051 |
| 1845 // Return the generated code. | 2052 // Return the generated code. |
| 1846 return GetCode(function); | 2053 return TryGetCode(function); |
| 1847 } | 2054 } |
| 1848 | 2055 |
| 1849 | 2056 |
| 1850 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2057 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
| 1851 Object* object, | 2058 Object* object, |
| 1852 JSObject* holder, | 2059 JSObject* holder, |
| 1853 JSGlobalPropertyCell* cell, | 2060 JSGlobalPropertyCell* cell, |
| 1854 JSFunction* function, | 2061 JSFunction* function, |
| 1855 String* name) { | 2062 String* name) { |
| 1856 // ----------- S t a t e ------------- | 2063 // ----------- S t a t e ------------- |
| 1857 // -- ecx : function name | 2064 // -- ecx : function name |
| 1858 // -- esp[0] : return address | 2065 // -- esp[0] : return address |
| 1859 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2066 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1860 // -- ... | 2067 // -- ... |
| 1861 // -- esp[(argc + 1) * 4] : receiver | 2068 // -- esp[(argc + 1) * 4] : receiver |
| 1862 // ----------------------------------- | 2069 // ----------------------------------- |
| 1863 | 2070 |
| 1864 const int argc = arguments().immediate(); | 2071 const int argc = arguments().immediate(); |
| 1865 | 2072 |
| 1866 // If the object is not a JSObject or we got an unexpected number of | 2073 // If the object is not a JSObject or we got an unexpected number of |
| 1867 // arguments, bail out to the regular call. | 2074 // arguments, bail out to the regular call. |
| 1868 if (!object->IsJSObject() || argc != 1) { | 2075 if (!object->IsJSObject() || argc != 1) { |
| 1869 return isolate()->heap()->undefined_value(); | 2076 return isolate()->heap()->undefined_value(); |
| 1870 } | 2077 } |
| 1871 | 2078 |
| 1872 Label miss; | 2079 Label miss; |
| 1873 GenerateNameCheck(name, &miss); | 2080 GenerateNameCheck(Handle<String>(name), &miss); |
| 1874 | 2081 |
| 1875 if (cell == NULL) { | 2082 if (cell == NULL) { |
| 1876 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2083 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1877 | 2084 |
| 1878 STATIC_ASSERT(kSmiTag == 0); | 2085 STATIC_ASSERT(kSmiTag == 0); |
| 1879 __ JumpIfSmi(edx, &miss); | 2086 __ JumpIfSmi(edx, &miss); |
| 1880 | 2087 |
| 1881 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2088 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
| 1882 &miss); | 2089 &miss); |
| 1883 } else { | 2090 } else { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1901 StringCharFromCodeGenerator char_from_code_generator(code, eax); | 2108 StringCharFromCodeGenerator char_from_code_generator(code, eax); |
| 1902 char_from_code_generator.GenerateFast(masm()); | 2109 char_from_code_generator.GenerateFast(masm()); |
| 1903 __ ret(2 * kPointerSize); | 2110 __ ret(2 * kPointerSize); |
| 1904 | 2111 |
| 1905 StubRuntimeCallHelper call_helper; | 2112 StubRuntimeCallHelper call_helper; |
| 1906 char_from_code_generator.GenerateSlow(masm(), call_helper); | 2113 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 1907 | 2114 |
| 1908 // Tail call the full function. We do not have to patch the receiver | 2115 // Tail call the full function. We do not have to patch the receiver |
| 1909 // because the function makes no use of it. | 2116 // because the function makes no use of it. |
| 1910 __ bind(&slow); | 2117 __ bind(&slow); |
| 1911 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2118 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1912 ? CALL_AS_FUNCTION | 2119 ? CALL_AS_FUNCTION |
| 1913 : CALL_AS_METHOD; | 2120 : CALL_AS_METHOD; |
| 1914 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2121 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1915 NullCallWrapper(), call_kind); | 2122 NullCallWrapper(), call_kind); |
| 1916 | 2123 |
| 1917 __ bind(&miss); | 2124 __ bind(&miss); |
| 1918 // ecx: function name. | 2125 // ecx: function name. |
| 1919 MaybeObject* maybe_result = GenerateMissBranch(); | 2126 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 1920 if (maybe_result->IsFailure()) return maybe_result; | 2127 if (maybe_result->IsFailure()) return maybe_result; |
| 1921 | 2128 |
| 1922 // Return the generated code. | 2129 // Return the generated code. |
| 1923 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2130 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 1924 } | 2131 } |
| 1925 | 2132 |
| 1926 | 2133 |
| 1927 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2134 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
| 1928 JSObject* holder, | 2135 JSObject* holder, |
| 1929 JSGlobalPropertyCell* cell, | 2136 JSGlobalPropertyCell* cell, |
| 1930 JSFunction* function, | 2137 JSFunction* function, |
| 1931 String* name) { | 2138 String* name) { |
| 1932 // ----------- S t a t e ------------- | 2139 // ----------- S t a t e ------------- |
| 1933 // -- ecx : name | 2140 // -- ecx : name |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1945 | 2152 |
| 1946 const int argc = arguments().immediate(); | 2153 const int argc = arguments().immediate(); |
| 1947 | 2154 |
| 1948 // If the object is not a JSObject or we got an unexpected number of | 2155 // If the object is not a JSObject or we got an unexpected number of |
| 1949 // arguments, bail out to the regular call. | 2156 // arguments, bail out to the regular call. |
| 1950 if (!object->IsJSObject() || argc != 1) { | 2157 if (!object->IsJSObject() || argc != 1) { |
| 1951 return isolate()->heap()->undefined_value(); | 2158 return isolate()->heap()->undefined_value(); |
| 1952 } | 2159 } |
| 1953 | 2160 |
| 1954 Label miss; | 2161 Label miss; |
| 1955 GenerateNameCheck(name, &miss); | 2162 GenerateNameCheck(Handle<String>(name), &miss); |
| 1956 | 2163 |
| 1957 if (cell == NULL) { | 2164 if (cell == NULL) { |
| 1958 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2165 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1959 | 2166 |
| 1960 STATIC_ASSERT(kSmiTag == 0); | 2167 STATIC_ASSERT(kSmiTag == 0); |
| 1961 __ JumpIfSmi(edx, &miss); | 2168 __ JumpIfSmi(edx, &miss); |
| 1962 | 2169 |
| 1963 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2170 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
| 1964 &miss); | 2171 &miss); |
| 1965 } else { | 2172 } else { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2038 __ ret(2 * kPointerSize); | 2245 __ ret(2 * kPointerSize); |
| 2039 | 2246 |
| 2040 // Tail call the full function. We do not have to patch the receiver | 2247 // Tail call the full function. We do not have to patch the receiver |
| 2041 // because the function makes no use of it. | 2248 // because the function makes no use of it. |
| 2042 __ bind(&slow); | 2249 __ bind(&slow); |
| 2043 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2250 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2044 NullCallWrapper(), CALL_AS_METHOD); | 2251 NullCallWrapper(), CALL_AS_METHOD); |
| 2045 | 2252 |
| 2046 __ bind(&miss); | 2253 __ bind(&miss); |
| 2047 // ecx: function name. | 2254 // ecx: function name. |
| 2048 MaybeObject* maybe_result = GenerateMissBranch(); | 2255 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2049 if (maybe_result->IsFailure()) return maybe_result; | 2256 if (maybe_result->IsFailure()) return maybe_result; |
| 2050 | 2257 |
| 2051 // Return the generated code. | 2258 // Return the generated code. |
| 2052 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2259 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2053 } | 2260 } |
| 2054 | 2261 |
| 2055 | 2262 |
| 2056 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2263 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
| 2057 JSObject* holder, | 2264 JSObject* holder, |
| 2058 JSGlobalPropertyCell* cell, | 2265 JSGlobalPropertyCell* cell, |
| 2059 JSFunction* function, | 2266 JSFunction* function, |
| 2060 String* name) { | 2267 String* name) { |
| 2061 // ----------- S t a t e ------------- | 2268 // ----------- S t a t e ------------- |
| 2062 // -- ecx : name | 2269 // -- ecx : name |
| 2063 // -- esp[0] : return address | 2270 // -- esp[0] : return address |
| 2064 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2271 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2065 // -- ... | 2272 // -- ... |
| 2066 // -- esp[(argc + 1) * 4] : receiver | 2273 // -- esp[(argc + 1) * 4] : receiver |
| 2067 // ----------------------------------- | 2274 // ----------------------------------- |
| 2068 | 2275 |
| 2069 const int argc = arguments().immediate(); | 2276 const int argc = arguments().immediate(); |
| 2070 | 2277 |
| 2071 // If the object is not a JSObject or we got an unexpected number of | 2278 // If the object is not a JSObject or we got an unexpected number of |
| 2072 // arguments, bail out to the regular call. | 2279 // arguments, bail out to the regular call. |
| 2073 if (!object->IsJSObject() || argc != 1) { | 2280 if (!object->IsJSObject() || argc != 1) { |
| 2074 return isolate()->heap()->undefined_value(); | 2281 return isolate()->heap()->undefined_value(); |
| 2075 } | 2282 } |
| 2076 | 2283 |
| 2077 Label miss; | 2284 Label miss; |
| 2078 GenerateNameCheck(name, &miss); | 2285 GenerateNameCheck(Handle<String>(name), &miss); |
| 2079 | 2286 |
| 2080 if (cell == NULL) { | 2287 if (cell == NULL) { |
| 2081 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2288 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2082 | 2289 |
| 2083 STATIC_ASSERT(kSmiTag == 0); | 2290 STATIC_ASSERT(kSmiTag == 0); |
| 2084 __ JumpIfSmi(edx, &miss); | 2291 __ JumpIfSmi(edx, &miss); |
| 2085 | 2292 |
| 2086 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2293 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
| 2087 &miss); | 2294 &miss); |
| 2088 } else { | 2295 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 __ ret(2 * kPointerSize); | 2349 __ ret(2 * kPointerSize); |
| 2143 | 2350 |
| 2144 // Tail call the full function. We do not have to patch the receiver | 2351 // Tail call the full function. We do not have to patch the receiver |
| 2145 // because the function makes no use of it. | 2352 // because the function makes no use of it. |
| 2146 __ bind(&slow); | 2353 __ bind(&slow); |
| 2147 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2354 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2148 NullCallWrapper(), CALL_AS_METHOD); | 2355 NullCallWrapper(), CALL_AS_METHOD); |
| 2149 | 2356 |
| 2150 __ bind(&miss); | 2357 __ bind(&miss); |
| 2151 // ecx: function name. | 2358 // ecx: function name. |
| 2152 MaybeObject* maybe_result = GenerateMissBranch(); | 2359 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2153 if (maybe_result->IsFailure()) return maybe_result; | 2360 if (maybe_result->IsFailure()) return maybe_result; |
| 2154 | 2361 |
| 2155 // Return the generated code. | 2362 // Return the generated code. |
| 2156 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2363 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
| 2157 } | 2364 } |
| 2158 | 2365 |
| 2159 | 2366 |
| 2160 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2367 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2161 const CallOptimization& optimization, | 2368 const CallOptimization& optimization, |
| 2162 Object* object, | 2369 Object* object, |
| 2163 JSObject* holder, | 2370 JSObject* holder, |
| 2164 JSGlobalPropertyCell* cell, | 2371 JSGlobalPropertyCell* cell, |
| 2165 JSFunction* function, | 2372 JSFunction* function, |
| 2166 String* name) { | 2373 String* name) { |
| 2167 ASSERT(optimization.is_simple_api_call()); | 2374 ASSERT(optimization.is_simple_api_call()); |
| 2168 // Bail out if object is a global object as we don't want to | 2375 // Bail out if object is a global object as we don't want to |
| 2169 // repatch it to global receiver. | 2376 // repatch it to global receiver. |
| 2170 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2377 if (object->IsGlobalObject()) return heap()->undefined_value(); |
| 2171 if (cell != NULL) return heap()->undefined_value(); | 2378 if (cell != NULL) return heap()->undefined_value(); |
| 2172 if (!object->IsJSObject()) return heap()->undefined_value(); | 2379 if (!object->IsJSObject()) return heap()->undefined_value(); |
| 2173 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2380 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2174 JSObject::cast(object), holder); | 2381 JSObject::cast(object), holder); |
| 2175 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2382 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
| 2176 | 2383 |
| 2177 Label miss, miss_before_stack_reserved; | 2384 Label miss, miss_before_stack_reserved; |
| 2178 | 2385 |
| 2179 GenerateNameCheck(name, &miss_before_stack_reserved); | 2386 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
| 2180 | 2387 |
| 2181 // Get the receiver from the stack. | 2388 // Get the receiver from the stack. |
| 2182 const int argc = arguments().immediate(); | 2389 const int argc = arguments().immediate(); |
| 2183 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2390 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2184 | 2391 |
| 2185 // Check that the receiver isn't a smi. | 2392 // Check that the receiver isn't a smi. |
| 2186 __ JumpIfSmi(edx, &miss_before_stack_reserved); | 2393 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
| 2187 | 2394 |
| 2188 Counters* counters = isolate()->counters(); | 2395 Counters* counters = isolate()->counters(); |
| 2189 __ IncrementCounter(counters->call_const(), 1); | 2396 __ IncrementCounter(counters->call_const(), 1); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2203 | 2410 |
| 2204 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2411 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2205 // duplicate of return address and will be overwritten. | 2412 // duplicate of return address and will be overwritten. |
| 2206 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2413 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2207 if (result->IsFailure()) return result; | 2414 if (result->IsFailure()) return result; |
| 2208 | 2415 |
| 2209 __ bind(&miss); | 2416 __ bind(&miss); |
| 2210 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2417 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2211 | 2418 |
| 2212 __ bind(&miss_before_stack_reserved); | 2419 __ bind(&miss_before_stack_reserved); |
| 2213 MaybeObject* maybe_result = GenerateMissBranch(); | 2420 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2214 if (maybe_result->IsFailure()) return maybe_result; | 2421 if (maybe_result->IsFailure()) return maybe_result; |
| 2215 | 2422 |
| 2216 // Return the generated code. | 2423 // Return the generated code. |
| 2217 return GetCode(function); | 2424 return TryGetCode(function); |
| 2218 } | 2425 } |
| 2219 | 2426 |
| 2220 | 2427 |
| 2221 MaybeObject* CallStubCompiler::CompileCallConstant( | 2428 MaybeObject* CallStubCompiler::CompileCallConstant( |
| 2222 Object* object, | 2429 Object* object, |
| 2223 JSObject* holder, | 2430 JSObject* holder, |
| 2224 JSFunction* function, | 2431 JSFunction* function, |
| 2225 String* name, | 2432 String* name, |
| 2226 CheckType check) { | 2433 CheckType check) { |
| 2227 // ----------- S t a t e ------------- | 2434 // ----------- S t a t e ------------- |
| 2228 // -- ecx : name | 2435 // -- ecx : name |
| 2229 // -- esp[0] : return address | 2436 // -- esp[0] : return address |
| 2230 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2437 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2231 // -- ... | 2438 // -- ... |
| 2232 // -- esp[(argc + 1) * 4] : receiver | 2439 // -- esp[(argc + 1) * 4] : receiver |
| 2233 // ----------------------------------- | 2440 // ----------------------------------- |
| 2234 | 2441 |
| 2235 if (HasCustomCallGenerator(function)) { | 2442 if (HasCustomCallGenerator(function)) { |
| 2236 MaybeObject* maybe_result = CompileCustomCall( | 2443 MaybeObject* maybe_result = CompileCustomCall( |
| 2237 object, holder, NULL, function, name); | 2444 object, holder, NULL, function, name); |
| 2238 Object* result; | 2445 Object* result; |
| 2239 if (!maybe_result->ToObject(&result)) return maybe_result; | 2446 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2240 // undefined means bail out to regular compiler. | 2447 // undefined means bail out to regular compiler. |
| 2241 if (!result->IsUndefined()) return result; | 2448 if (!result->IsUndefined()) return result; |
| 2242 } | 2449 } |
| 2243 | 2450 |
| 2244 Label miss; | 2451 Label miss; |
| 2245 | 2452 |
| 2246 GenerateNameCheck(name, &miss); | 2453 GenerateNameCheck(Handle<String>(name), &miss); |
| 2247 | 2454 |
| 2248 // Get the receiver from the stack. | 2455 // Get the receiver from the stack. |
| 2249 const int argc = arguments().immediate(); | 2456 const int argc = arguments().immediate(); |
| 2250 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2457 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2251 | 2458 |
| 2252 // Check that the receiver isn't a smi. | 2459 // Check that the receiver isn't a smi. |
| 2253 if (check != NUMBER_CHECK) { | 2460 if (check != NUMBER_CHECK) { |
| 2254 __ JumpIfSmi(edx, &miss); | 2461 __ JumpIfSmi(edx, &miss); |
| 2255 } | 2462 } |
| 2256 | 2463 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2332 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2539 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 2333 ebx, edx, edi, name, &miss); | 2540 ebx, edx, edi, name, &miss); |
| 2334 } | 2541 } |
| 2335 break; | 2542 break; |
| 2336 } | 2543 } |
| 2337 | 2544 |
| 2338 default: | 2545 default: |
| 2339 UNREACHABLE(); | 2546 UNREACHABLE(); |
| 2340 } | 2547 } |
| 2341 | 2548 |
| 2342 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2549 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2343 ? CALL_AS_FUNCTION | 2550 ? CALL_AS_FUNCTION |
| 2344 : CALL_AS_METHOD; | 2551 : CALL_AS_METHOD; |
| 2345 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2552 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2346 NullCallWrapper(), call_kind); | 2553 NullCallWrapper(), call_kind); |
| 2347 | 2554 |
| 2348 // Handle call cache miss. | 2555 // Handle call cache miss. |
| 2349 __ bind(&miss); | 2556 __ bind(&miss); |
| 2350 MaybeObject* maybe_result = GenerateMissBranch(); | 2557 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2351 if (maybe_result->IsFailure()) return maybe_result; | 2558 if (maybe_result->IsFailure()) return maybe_result; |
| 2352 | 2559 |
| 2353 // Return the generated code. | 2560 // Return the generated code. |
| 2354 return GetCode(function); | 2561 return TryGetCode(function); |
| 2355 } | 2562 } |
| 2356 | 2563 |
| 2357 | 2564 |
| 2358 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2565 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 2359 JSObject* holder, | 2566 JSObject* holder, |
| 2360 String* name) { | 2567 String* name) { |
| 2361 // ----------- S t a t e ------------- | 2568 // ----------- S t a t e ------------- |
| 2362 // -- ecx : name | 2569 // -- ecx : name |
| 2363 // -- esp[0] : return address | 2570 // -- esp[0] : return address |
| 2364 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2571 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2365 // -- ... | 2572 // -- ... |
| 2366 // -- esp[(argc + 1) * 4] : receiver | 2573 // -- esp[(argc + 1) * 4] : receiver |
| 2367 // ----------------------------------- | 2574 // ----------------------------------- |
| 2368 Label miss; | 2575 Label miss; |
| 2369 | 2576 |
| 2370 GenerateNameCheck(name, &miss); | 2577 GenerateNameCheck(Handle<String>(name), &miss); |
| 2371 | 2578 |
| 2372 // Get the number of arguments. | 2579 // Get the number of arguments. |
| 2373 const int argc = arguments().immediate(); | 2580 const int argc = arguments().immediate(); |
| 2374 | 2581 |
| 2375 LookupResult lookup; | 2582 LookupResult lookup(isolate()); |
| 2376 LookupPostInterceptor(holder, name, &lookup); | 2583 LookupPostInterceptor(holder, name, &lookup); |
| 2377 | 2584 |
| 2378 // Get the receiver from the stack. | 2585 // Get the receiver from the stack. |
| 2379 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2586 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2380 | 2587 |
| 2381 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_ic_state_); | 2588 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); |
| 2382 MaybeObject* result = compiler.Compile(masm(), | 2589 MaybeObject* result = compiler.Compile(masm(), |
| 2383 object, | 2590 object, |
| 2384 holder, | 2591 holder, |
| 2385 name, | 2592 name, |
| 2386 &lookup, | 2593 &lookup, |
| 2387 edx, | 2594 edx, |
| 2388 ebx, | 2595 ebx, |
| 2389 edi, | 2596 edi, |
| 2390 eax, | 2597 eax, |
| 2391 &miss); | 2598 &miss); |
| 2392 if (result->IsFailure()) return result; | 2599 if (result->IsFailure()) return result; |
| 2393 | 2600 |
| 2394 // Restore receiver. | 2601 // Restore receiver. |
| 2395 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2602 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2396 | 2603 |
| 2397 // Check that the function really is a function. | 2604 // Check that the function really is a function. |
| 2398 __ JumpIfSmi(eax, &miss); | 2605 __ JumpIfSmi(eax, &miss); |
| 2399 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2606 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 2400 __ j(not_equal, &miss); | 2607 __ j(not_equal, &miss); |
| 2401 | 2608 |
| 2402 // Patch the receiver on the stack with the global proxy if | 2609 // Patch the receiver on the stack with the global proxy if |
| 2403 // necessary. | 2610 // necessary. |
| 2404 if (object->IsGlobalObject()) { | 2611 if (object->IsGlobalObject()) { |
| 2405 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2612 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2406 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2613 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2407 } | 2614 } |
| 2408 | 2615 |
| 2409 // Invoke the function. | 2616 // Invoke the function. |
| 2410 __ mov(edi, eax); | 2617 __ mov(edi, eax); |
| 2411 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2618 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2412 ? CALL_AS_FUNCTION | 2619 ? CALL_AS_FUNCTION |
| 2413 : CALL_AS_METHOD; | 2620 : CALL_AS_METHOD; |
| 2414 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 2621 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 2415 NullCallWrapper(), call_kind); | 2622 NullCallWrapper(), call_kind); |
| 2416 | 2623 |
| 2417 // Handle load cache miss. | 2624 // Handle load cache miss. |
| 2418 __ bind(&miss); | 2625 __ bind(&miss); |
| 2419 MaybeObject* maybe_result = GenerateMissBranch(); | 2626 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2420 if (maybe_result->IsFailure()) return maybe_result; | 2627 if (maybe_result->IsFailure()) return maybe_result; |
| 2421 | 2628 |
| 2422 // Return the generated code. | 2629 // Return the generated code. |
| 2423 return GetCode(INTERCEPTOR, name); | 2630 return TryGetCode(INTERCEPTOR, name); |
| 2424 } | 2631 } |
| 2425 | 2632 |
| 2426 | 2633 |
| 2427 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2634 MaybeObject* CallStubCompiler::CompileCallGlobal( |
| 2428 JSObject* object, | 2635 JSObject* object, |
| 2429 GlobalObject* holder, | 2636 GlobalObject* holder, |
| 2430 JSGlobalPropertyCell* cell, | 2637 JSGlobalPropertyCell* cell, |
| 2431 JSFunction* function, | 2638 JSFunction* function, |
| 2432 String* name) { | 2639 String* name) { |
| 2433 // ----------- S t a t e ------------- | 2640 // ----------- S t a t e ------------- |
| 2434 // -- ecx : name | 2641 // -- ecx : name |
| 2435 // -- esp[0] : return address | 2642 // -- esp[0] : return address |
| 2436 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2643 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2437 // -- ... | 2644 // -- ... |
| 2438 // -- esp[(argc + 1) * 4] : receiver | 2645 // -- esp[(argc + 1) * 4] : receiver |
| 2439 // ----------------------------------- | 2646 // ----------------------------------- |
| 2440 | 2647 |
| 2441 if (HasCustomCallGenerator(function)) { | 2648 if (HasCustomCallGenerator(function)) { |
| 2442 MaybeObject* maybe_result = CompileCustomCall( | 2649 MaybeObject* maybe_result = CompileCustomCall( |
| 2443 object, holder, cell, function, name); | 2650 object, holder, cell, function, name); |
| 2444 Object* result; | 2651 Object* result; |
| 2445 if (!maybe_result->ToObject(&result)) return maybe_result; | 2652 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2446 // undefined means bail out to regular compiler. | 2653 // undefined means bail out to regular compiler. |
| 2447 if (!result->IsUndefined()) return result; | 2654 if (!result->IsUndefined()) return result; |
| 2448 } | 2655 } |
| 2449 | 2656 |
| 2450 Label miss; | 2657 Label miss; |
| 2451 | 2658 |
| 2452 GenerateNameCheck(name, &miss); | 2659 GenerateNameCheck(Handle<String>(name), &miss); |
| 2453 | 2660 |
| 2454 // Get the number of arguments. | 2661 // Get the number of arguments. |
| 2455 const int argc = arguments().immediate(); | 2662 const int argc = arguments().immediate(); |
| 2456 | 2663 |
| 2457 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2664 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2458 | 2665 |
| 2459 GenerateLoadFunctionFromCell(cell, function, &miss); | 2666 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2460 | 2667 |
| 2461 // Patch the receiver on the stack with the global proxy. | 2668 // Patch the receiver on the stack with the global proxy. |
| 2462 if (object->IsGlobalObject()) { | 2669 if (object->IsGlobalObject()) { |
| 2463 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2670 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2464 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2671 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2465 } | 2672 } |
| 2466 | 2673 |
| 2467 // Setup the context (function already in edi). | 2674 // Setup the context (function already in edi). |
| 2468 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2675 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 2469 | 2676 |
| 2470 // Jump to the cached code (tail call). | 2677 // Jump to the cached code (tail call). |
| 2471 Counters* counters = isolate()->counters(); | 2678 Counters* counters = isolate()->counters(); |
| 2472 __ IncrementCounter(counters->call_global_inline(), 1); | 2679 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2473 ASSERT(function->is_compiled()); | |
| 2474 ParameterCount expected(function->shared()->formal_parameter_count()); | 2680 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2475 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2681 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2476 ? CALL_AS_FUNCTION | 2682 ? CALL_AS_FUNCTION |
| 2477 : CALL_AS_METHOD; | 2683 : CALL_AS_METHOD; |
| 2478 if (V8::UseCrankshaft()) { | 2684 // We call indirectly through the code field in the function to |
| 2479 // TODO(kasperl): For now, we always call indirectly through the | 2685 // allow recompilation to take effect without changing any of the |
| 2480 // code field in the function to allow recompilation to take effect | 2686 // call sites. |
| 2481 // without changing any of the call sites. | 2687 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
| 2482 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2688 expected, arguments(), JUMP_FUNCTION, |
| 2483 expected, arguments(), JUMP_FUNCTION, | 2689 NullCallWrapper(), call_kind); |
| 2484 NullCallWrapper(), call_kind); | |
| 2485 } else { | |
| 2486 Handle<Code> code(function->code()); | |
| 2487 __ InvokeCode(code, expected, arguments(), | |
| 2488 RelocInfo::CODE_TARGET, JUMP_FUNCTION, | |
| 2489 NullCallWrapper(), call_kind); | |
| 2490 } | |
| 2491 | 2690 |
| 2492 // Handle call cache miss. | 2691 // Handle call cache miss. |
| 2493 __ bind(&miss); | 2692 __ bind(&miss); |
| 2494 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2693 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2495 MaybeObject* maybe_result = GenerateMissBranch(); | 2694 MaybeObject* maybe_result = TryGenerateMissBranch(); |
| 2496 if (maybe_result->IsFailure()) return maybe_result; | 2695 if (maybe_result->IsFailure()) return maybe_result; |
| 2497 | 2696 |
| 2498 // Return the generated code. | 2697 // Return the generated code. |
| 2499 return GetCode(NORMAL, name); | 2698 return TryGetCode(NORMAL, name); |
| 2500 } | 2699 } |
| 2501 | 2700 |
| 2502 | 2701 |
| 2503 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2702 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2504 int index, | 2703 int index, |
| 2505 Map* transition, | 2704 Handle<Map> transition, |
| 2506 String* name) { | 2705 Handle<String> name) { |
| 2507 // ----------- S t a t e ------------- | 2706 // ----------- S t a t e ------------- |
| 2508 // -- eax : value | 2707 // -- eax : value |
| 2509 // -- ecx : name | 2708 // -- ecx : name |
| 2510 // -- edx : receiver | 2709 // -- edx : receiver |
| 2511 // -- esp[0] : return address | 2710 // -- esp[0] : return address |
| 2512 // ----------------------------------- | 2711 // ----------------------------------- |
| 2513 Label miss; | 2712 Label miss; |
| 2514 | 2713 |
| 2515 // Generate store field code. Trashes the name register. | 2714 // Generate store field code. Trashes the name register. |
| 2516 GenerateStoreField(masm(), | 2715 GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); |
| 2517 object, | |
| 2518 index, | |
| 2519 transition, | |
| 2520 edx, ecx, ebx, | |
| 2521 &miss); | |
| 2522 | 2716 |
| 2523 // Handle store cache miss. | 2717 // Handle store cache miss. |
| 2524 __ bind(&miss); | 2718 __ bind(&miss); |
| 2525 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 2719 __ mov(ecx, Immediate(name)); // restore name |
| 2526 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2720 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2527 __ jmp(ic, RelocInfo::CODE_TARGET); | 2721 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2528 | 2722 |
| 2529 // Return the generated code. | 2723 // Return the generated code. |
| 2530 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2724 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
| 2531 } | 2725 } |
| 2532 | 2726 |
| 2533 | 2727 |
| 2534 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2728 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2535 AccessorInfo* callback, | 2729 Handle<JSObject> object, |
| 2536 String* name) { | 2730 Handle<AccessorInfo> callback, |
| 2731 Handle<String> name) { |
| 2537 // ----------- S t a t e ------------- | 2732 // ----------- S t a t e ------------- |
| 2538 // -- eax : value | 2733 // -- eax : value |
| 2539 // -- ecx : name | 2734 // -- ecx : name |
| 2540 // -- edx : receiver | 2735 // -- edx : receiver |
| 2541 // -- esp[0] : return address | 2736 // -- esp[0] : return address |
| 2542 // ----------------------------------- | 2737 // ----------------------------------- |
| 2543 Label miss; | 2738 Label miss; |
| 2544 | 2739 |
| 2545 // Check that the object isn't a smi. | 2740 // Check that the object isn't a smi. |
| 2546 __ JumpIfSmi(edx, &miss); | 2741 __ JumpIfSmi(edx, &miss); |
| 2547 | 2742 |
| 2548 // Check that the map of the object hasn't changed. | 2743 // Check that the map of the object hasn't changed. |
| 2549 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2744 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2550 Immediate(Handle<Map>(object->map()))); | 2745 Immediate(Handle<Map>(object->map()))); |
| 2551 __ j(not_equal, &miss); | 2746 __ j(not_equal, &miss); |
| 2552 | 2747 |
| 2553 // Perform global security token check if needed. | 2748 // Perform global security token check if needed. |
| 2554 if (object->IsJSGlobalProxy()) { | 2749 if (object->IsJSGlobalProxy()) { |
| 2555 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2750 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
| 2556 } | 2751 } |
| 2557 | 2752 |
| 2558 // Stub never generated for non-global objects that require access | 2753 // Stub never generated for non-global objects that require access |
| 2559 // checks. | 2754 // checks. |
| 2560 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2755 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2561 | 2756 |
| 2562 __ pop(ebx); // remove the return address | 2757 __ pop(ebx); // remove the return address |
| 2563 __ push(edx); // receiver | 2758 __ push(edx); // receiver |
| 2564 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info | 2759 __ push(Immediate(callback)); // callback info |
| 2565 __ push(ecx); // name | 2760 __ push(ecx); // name |
| 2566 __ push(eax); // value | 2761 __ push(eax); // value |
| 2567 __ push(ebx); // restore return address | 2762 __ push(ebx); // restore return address |
| 2568 | 2763 |
| 2569 // Do tail-call to the runtime system. | 2764 // Do tail-call to the runtime system. |
| 2570 ExternalReference store_callback_property = | 2765 ExternalReference store_callback_property = |
| 2571 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2766 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2572 __ TailCallExternalReference(store_callback_property, 4, 1); | 2767 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2573 | 2768 |
| 2574 // Handle store cache miss. | 2769 // Handle store cache miss. |
| 2575 __ bind(&miss); | 2770 __ bind(&miss); |
| 2576 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2771 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2577 __ jmp(ic, RelocInfo::CODE_TARGET); | 2772 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2578 | 2773 |
| 2579 // Return the generated code. | 2774 // Return the generated code. |
| 2580 return GetCode(CALLBACKS, name); | 2775 return GetCode(CALLBACKS, name); |
| 2581 } | 2776 } |
| 2582 | 2777 |
| 2583 | 2778 |
| 2584 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2779 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 2585 String* name) { | 2780 Handle<JSObject> receiver, |
| 2781 Handle<String> name) { |
| 2586 // ----------- S t a t e ------------- | 2782 // ----------- S t a t e ------------- |
| 2587 // -- eax : value | 2783 // -- eax : value |
| 2588 // -- ecx : name | 2784 // -- ecx : name |
| 2589 // -- edx : receiver | 2785 // -- edx : receiver |
| 2590 // -- esp[0] : return address | 2786 // -- esp[0] : return address |
| 2591 // ----------------------------------- | 2787 // ----------------------------------- |
| 2592 Label miss; | 2788 Label miss; |
| 2593 | 2789 |
| 2594 // Check that the object isn't a smi. | 2790 // Check that the object isn't a smi. |
| 2595 __ JumpIfSmi(edx, &miss); | 2791 __ JumpIfSmi(edx, &miss); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2623 // Handle store cache miss. | 2819 // Handle store cache miss. |
| 2624 __ bind(&miss); | 2820 __ bind(&miss); |
| 2625 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2821 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2626 __ jmp(ic, RelocInfo::CODE_TARGET); | 2822 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2627 | 2823 |
| 2628 // Return the generated code. | 2824 // Return the generated code. |
| 2629 return GetCode(INTERCEPTOR, name); | 2825 return GetCode(INTERCEPTOR, name); |
| 2630 } | 2826 } |
| 2631 | 2827 |
| 2632 | 2828 |
| 2633 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2829 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
| 2634 JSGlobalPropertyCell* cell, | 2830 Handle<GlobalObject> object, |
| 2635 String* name) { | 2831 Handle<JSGlobalPropertyCell> cell, |
| 2832 Handle<String> name) { |
| 2636 // ----------- S t a t e ------------- | 2833 // ----------- S t a t e ------------- |
| 2637 // -- eax : value | 2834 // -- eax : value |
| 2638 // -- ecx : name | 2835 // -- ecx : name |
| 2639 // -- edx : receiver | 2836 // -- edx : receiver |
| 2640 // -- esp[0] : return address | 2837 // -- esp[0] : return address |
| 2641 // ----------------------------------- | 2838 // ----------------------------------- |
| 2642 Label miss; | 2839 Label miss; |
| 2643 | 2840 |
| 2644 // Check that the map of the global has not changed. | 2841 // Check that the map of the global has not changed. |
| 2645 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2842 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2646 Immediate(Handle<Map>(object->map()))); | 2843 Immediate(Handle<Map>(object->map()))); |
| 2647 __ j(not_equal, &miss); | 2844 __ j(not_equal, &miss); |
| 2648 | 2845 |
| 2649 // Compute the cell operand to use. | 2846 // Compute the cell operand to use. |
| 2650 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2847 __ mov(ebx, Immediate(cell)); |
| 2651 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2848 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
| 2652 | 2849 |
| 2653 // Check that the value in the cell is not the hole. If it is, this | 2850 // Check that the value in the cell is not the hole. If it is, this |
| 2654 // cell could have been deleted and reintroducing the global needs | 2851 // cell could have been deleted and reintroducing the global needs |
| 2655 // to update the property details in the property dictionary of the | 2852 // to update the property details in the property dictionary of the |
| 2656 // global object. We bail out to the runtime system to do that. | 2853 // global object. We bail out to the runtime system to do that. |
| 2657 __ cmp(cell_operand, factory()->the_hole_value()); | 2854 __ cmp(cell_operand, factory()->the_hole_value()); |
| 2658 __ j(equal, &miss); | 2855 __ j(equal, &miss); |
| 2659 | 2856 |
| 2660 // Store the value in the cell. | 2857 // Store the value in the cell. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2684 __ bind(&miss); | 2881 __ bind(&miss); |
| 2685 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2882 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
| 2686 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2883 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2687 __ jmp(ic, RelocInfo::CODE_TARGET); | 2884 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2688 | 2885 |
| 2689 // Return the generated code. | 2886 // Return the generated code. |
| 2690 return GetCode(NORMAL, name); | 2887 return GetCode(NORMAL, name); |
| 2691 } | 2888 } |
| 2692 | 2889 |
| 2693 | 2890 |
| 2694 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2891 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2695 int index, | 2892 int index, |
| 2696 Map* transition, | 2893 Handle<Map> transition, |
| 2697 String* name) { | 2894 Handle<String> name) { |
| 2698 // ----------- S t a t e ------------- | 2895 // ----------- S t a t e ------------- |
| 2699 // -- eax : value | 2896 // -- eax : value |
| 2700 // -- ecx : key | 2897 // -- ecx : key |
| 2701 // -- edx : receiver | 2898 // -- edx : receiver |
| 2702 // -- esp[0] : return address | 2899 // -- esp[0] : return address |
| 2703 // ----------------------------------- | 2900 // ----------------------------------- |
| 2704 Label miss; | 2901 Label miss; |
| 2705 | 2902 |
| 2706 Counters* counters = isolate()->counters(); | 2903 Counters* counters = isolate()->counters(); |
| 2707 __ IncrementCounter(counters->keyed_store_field(), 1); | 2904 __ IncrementCounter(counters->keyed_store_field(), 1); |
| 2708 | 2905 |
| 2709 // Check that the name has not changed. | 2906 // Check that the name has not changed. |
| 2710 __ cmp(ecx, Immediate(Handle<String>(name))); | 2907 __ cmp(ecx, Immediate(name)); |
| 2711 __ j(not_equal, &miss); | 2908 __ j(not_equal, &miss); |
| 2712 | 2909 |
| 2713 // Generate store field code. Trashes the name register. | 2910 // Generate store field code. Trashes the name register. |
| 2714 GenerateStoreField(masm(), | 2911 GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); |
| 2715 object, | |
| 2716 index, | |
| 2717 transition, | |
| 2718 edx, ecx, ebx, | |
| 2719 &miss); | |
| 2720 | 2912 |
| 2721 // Handle store cache miss. | 2913 // Handle store cache miss. |
| 2722 __ bind(&miss); | 2914 __ bind(&miss); |
| 2723 __ DecrementCounter(counters->keyed_store_field(), 1); | 2915 __ DecrementCounter(counters->keyed_store_field(), 1); |
| 2724 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2916 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2725 __ jmp(ic, RelocInfo::CODE_TARGET); | 2917 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2726 | 2918 |
| 2727 // Return the generated code. | 2919 // Return the generated code. |
| 2728 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2920 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
| 2729 } | 2921 } |
| 2730 | 2922 |
| 2731 | 2923 |
| 2732 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { | 2924 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
| 2925 Handle<Map> receiver_map) { |
| 2733 // ----------- S t a t e ------------- | 2926 // ----------- S t a t e ------------- |
| 2734 // -- eax : value | 2927 // -- eax : value |
| 2735 // -- ecx : key | 2928 // -- ecx : key |
| 2736 // -- edx : receiver | 2929 // -- edx : receiver |
| 2737 // -- esp[0] : return address | 2930 // -- esp[0] : return address |
| 2738 // ----------------------------------- | 2931 // ----------------------------------- |
| 2739 Code* stub; | |
| 2740 ElementsKind elements_kind = receiver_map->elements_kind(); | 2932 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 2741 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2933 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 2742 MaybeObject* maybe_stub = | 2934 Handle<Code> stub = |
| 2743 KeyedStoreElementStub(is_jsarray, elements_kind).TryGetCode(); | 2935 KeyedStoreElementStub(is_jsarray, elements_kind).GetCode(); |
| 2744 if (!maybe_stub->To(&stub)) return maybe_stub; | 2936 |
| 2745 __ DispatchMap(edx, | 2937 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 2746 Handle<Map>(receiver_map), | |
| 2747 Handle<Code>(stub), | |
| 2748 DO_SMI_CHECK); | |
| 2749 | 2938 |
| 2750 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2939 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2751 __ jmp(ic, RelocInfo::CODE_TARGET); | 2940 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2752 | 2941 |
| 2753 // Return the generated code. | 2942 // Return the generated code. |
| 2754 return GetCode(NORMAL, NULL); | 2943 return GetCode(NORMAL, factory()->empty_string()); |
| 2755 } | 2944 } |
| 2756 | 2945 |
| 2757 | 2946 |
| 2758 MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic( | 2947 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
| 2759 MapList* receiver_maps, | 2948 MapHandleList* receiver_maps, |
| 2760 CodeList* handler_stubs, | 2949 CodeHandleList* handler_stubs, |
| 2761 MapList* transitioned_maps) { | 2950 MapHandleList* transitioned_maps) { |
| 2762 // ----------- S t a t e ------------- | 2951 // ----------- S t a t e ------------- |
| 2763 // -- eax : value | 2952 // -- eax : value |
| 2764 // -- ecx : key | 2953 // -- ecx : key |
| 2765 // -- edx : receiver | 2954 // -- edx : receiver |
| 2766 // -- esp[0] : return address | 2955 // -- esp[0] : return address |
| 2767 // ----------------------------------- | 2956 // ----------------------------------- |
| 2768 Label miss; | 2957 Label miss; |
| 2769 __ JumpIfSmi(edx, &miss, Label::kNear); | 2958 __ JumpIfSmi(edx, &miss, Label::kNear); |
| 2770 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 2959 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 2771 // ebx: receiver->map(). | 2960 // ebx: receiver->map(). |
| 2772 for (int i = 0; i < receiver_maps->length(); ++i) { | 2961 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 2773 Handle<Map> map(receiver_maps->at(i)); | 2962 __ cmp(edi, receiver_maps->at(i)); |
| 2774 __ cmp(edi, map); | 2963 if (transitioned_maps->at(i).is_null()) { |
| 2775 if (transitioned_maps->at(i) == NULL) { | 2964 __ j(equal, handler_stubs->at(i)); |
| 2776 __ j(equal, Handle<Code>(handler_stubs->at(i))); | |
| 2777 } else { | 2965 } else { |
| 2778 Label next_map; | 2966 Label next_map; |
| 2779 __ j(not_equal, &next_map, Label::kNear); | 2967 __ j(not_equal, &next_map, Label::kNear); |
| 2780 __ mov(ebx, Immediate(Handle<Map>(transitioned_maps->at(i)))); | 2968 __ mov(ebx, Immediate(transitioned_maps->at(i))); |
| 2781 __ jmp(Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET); | 2969 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
| 2782 __ bind(&next_map); | 2970 __ bind(&next_map); |
| 2783 } | 2971 } |
| 2784 } | 2972 } |
| 2785 __ bind(&miss); | 2973 __ bind(&miss); |
| 2786 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2974 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2787 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 2975 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 2788 | 2976 |
| 2789 // Return the generated code. | 2977 // Return the generated code. |
| 2790 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 2978 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 2791 } | 2979 } |
| 2792 | 2980 |
| 2793 | 2981 |
| 2794 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2982 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, |
| 2795 JSObject* object, | 2983 Handle<JSObject> object, |
| 2796 JSObject* last) { | 2984 Handle<JSObject> last) { |
| 2797 // ----------- S t a t e ------------- | 2985 // ----------- S t a t e ------------- |
| 2798 // -- eax : receiver | 2986 // -- eax : receiver |
| 2799 // -- ecx : name | 2987 // -- ecx : name |
| 2800 // -- esp[0] : return address | 2988 // -- esp[0] : return address |
| 2801 // ----------------------------------- | 2989 // ----------------------------------- |
| 2802 Label miss; | 2990 Label miss; |
| 2803 | 2991 |
| 2804 // Check that the receiver isn't a smi. | 2992 // Check that the receiver isn't a smi. |
| 2805 __ JumpIfSmi(eax, &miss); | 2993 __ JumpIfSmi(eax, &miss); |
| 2806 | 2994 |
| 2807 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2995 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
| 2808 | 2996 |
| 2809 // Check the maps of the full prototype chain. Also check that | 2997 // Check the maps of the full prototype chain. Also check that |
| 2810 // global property cells up to (but not including) the last object | 2998 // global property cells up to (but not including) the last object |
| 2811 // in the prototype chain are empty. | 2999 // in the prototype chain are empty. |
| 2812 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 3000 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
| 2813 | 3001 |
| 2814 // If the last object in the prototype chain is a global object, | 3002 // If the last object in the prototype chain is a global object, |
| 2815 // check that the global property cell is empty. | 3003 // check that the global property cell is empty. |
| 2816 if (last->IsGlobalObject()) { | 3004 if (last->IsGlobalObject()) { |
| 2817 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 3005 GenerateCheckPropertyCell( |
| 2818 GlobalObject::cast(last), | 3006 masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); |
| 2819 name, | |
| 2820 edx, | |
| 2821 &miss); | |
| 2822 if (cell->IsFailure()) { | |
| 2823 miss.Unuse(); | |
| 2824 return cell; | |
| 2825 } | |
| 2826 } | 3007 } |
| 2827 | 3008 |
| 2828 // Return undefined if maps of the full prototype chain are still the | 3009 // Return undefined if maps of the full prototype chain are still the |
| 2829 // same and no global property with this name contains a value. | 3010 // same and no global property with this name contains a value. |
| 2830 __ mov(eax, isolate()->factory()->undefined_value()); | 3011 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2831 __ ret(0); | 3012 __ ret(0); |
| 2832 | 3013 |
| 2833 __ bind(&miss); | 3014 __ bind(&miss); |
| 2834 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3015 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2835 | 3016 |
| 2836 // Return the generated code. | 3017 // Return the generated code. |
| 2837 return GetCode(NONEXISTENT, isolate()->heap()->empty_string()); | 3018 return GetCode(NONEXISTENT, factory()->empty_string()); |
| 2838 } | 3019 } |
| 2839 | 3020 |
| 2840 | 3021 |
| 2841 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, | 3022 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
| 2842 JSObject* holder, | 3023 Handle<JSObject> holder, |
| 2843 int index, | 3024 int index, |
| 2844 String* name) { | 3025 Handle<String> name) { |
| 2845 // ----------- S t a t e ------------- | 3026 // ----------- S t a t e ------------- |
| 2846 // -- eax : receiver | 3027 // -- eax : receiver |
| 2847 // -- ecx : name | 3028 // -- ecx : name |
| 2848 // -- esp[0] : return address | 3029 // -- esp[0] : return address |
| 2849 // ----------------------------------- | 3030 // ----------------------------------- |
| 2850 Label miss; | 3031 Label miss; |
| 2851 | 3032 |
| 2852 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); | 3033 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); |
| 2853 __ bind(&miss); | 3034 __ bind(&miss); |
| 2854 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3035 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2873 edi, callback, name, &miss); | 3054 edi, callback, name, &miss); |
| 2874 if (result->IsFailure()) { | 3055 if (result->IsFailure()) { |
| 2875 miss.Unuse(); | 3056 miss.Unuse(); |
| 2876 return result; | 3057 return result; |
| 2877 } | 3058 } |
| 2878 | 3059 |
| 2879 __ bind(&miss); | 3060 __ bind(&miss); |
| 2880 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3061 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2881 | 3062 |
| 2882 // Return the generated code. | 3063 // Return the generated code. |
| 2883 return GetCode(CALLBACKS, name); | 3064 return TryGetCode(CALLBACKS, name); |
| 2884 } | 3065 } |
| 2885 | 3066 |
| 2886 | 3067 |
| 2887 MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 3068 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 2888 JSObject* holder, | 3069 Handle<JSObject> holder, |
| 2889 Object* value, | 3070 Handle<Object> value, |
| 2890 String* name) { | 3071 Handle<String> name) { |
| 2891 // ----------- S t a t e ------------- | 3072 // ----------- S t a t e ------------- |
| 2892 // -- eax : receiver | 3073 // -- eax : receiver |
| 2893 // -- ecx : name | 3074 // -- ecx : name |
| 2894 // -- esp[0] : return address | 3075 // -- esp[0] : return address |
| 2895 // ----------------------------------- | 3076 // ----------------------------------- |
| 2896 Label miss; | 3077 Label miss; |
| 2897 | 3078 |
| 2898 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); | 3079 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); |
| 2899 __ bind(&miss); | 3080 __ bind(&miss); |
| 2900 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3081 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2901 | 3082 |
| 2902 // Return the generated code. | 3083 // Return the generated code. |
| 2903 return GetCode(CONSTANT_FUNCTION, name); | 3084 return GetCode(CONSTANT_FUNCTION, name); |
| 2904 } | 3085 } |
| 2905 | 3086 |
| 2906 | 3087 |
| 2907 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3088 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 2908 JSObject* holder, | 3089 JSObject* holder, |
| 2909 String* name) { | 3090 String* name) { |
| 2910 // ----------- S t a t e ------------- | 3091 // ----------- S t a t e ------------- |
| 2911 // -- eax : receiver | 3092 // -- eax : receiver |
| 2912 // -- ecx : name | 3093 // -- ecx : name |
| 2913 // -- esp[0] : return address | 3094 // -- esp[0] : return address |
| 2914 // ----------------------------------- | 3095 // ----------------------------------- |
| 2915 Label miss; | 3096 Label miss; |
| 2916 | 3097 |
| 2917 LookupResult lookup; | 3098 LookupResult lookup(isolate()); |
| 2918 LookupPostInterceptor(holder, name, &lookup); | 3099 LookupPostInterceptor(holder, name, &lookup); |
| 2919 | 3100 |
| 2920 // TODO(368): Compile in the whole chain: all the interceptors in | 3101 // TODO(368): Compile in the whole chain: all the interceptors in |
| 2921 // prototypes and ultimate answer. | 3102 // prototypes and ultimate answer. |
| 2922 GenerateLoadInterceptor(receiver, | 3103 GenerateLoadInterceptor(receiver, |
| 2923 holder, | 3104 holder, |
| 2924 &lookup, | 3105 &lookup, |
| 2925 eax, | 3106 eax, |
| 2926 ecx, | 3107 ecx, |
| 2927 edx, | 3108 edx, |
| 2928 ebx, | 3109 ebx, |
| 2929 edi, | 3110 edi, |
| 2930 name, | 3111 name, |
| 2931 &miss); | 3112 &miss); |
| 2932 | 3113 |
| 2933 __ bind(&miss); | 3114 __ bind(&miss); |
| 2934 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3115 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2935 | 3116 |
| 2936 // Return the generated code. | 3117 // Return the generated code. |
| 2937 return GetCode(INTERCEPTOR, name); | 3118 return TryGetCode(INTERCEPTOR, name); |
| 2938 } | 3119 } |
| 2939 | 3120 |
| 2940 | 3121 |
| 2941 MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, | 3122 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 2942 GlobalObject* holder, | 3123 Handle<JSObject> object, |
| 2943 JSGlobalPropertyCell* cell, | 3124 Handle<GlobalObject> holder, |
| 2944 String* name, | 3125 Handle<JSGlobalPropertyCell> cell, |
| 2945 bool is_dont_delete) { | 3126 Handle<String> name, |
| 3127 bool is_dont_delete) { |
| 2946 // ----------- S t a t e ------------- | 3128 // ----------- S t a t e ------------- |
| 2947 // -- eax : receiver | 3129 // -- eax : receiver |
| 2948 // -- ecx : name | 3130 // -- ecx : name |
| 2949 // -- esp[0] : return address | 3131 // -- esp[0] : return address |
| 2950 // ----------------------------------- | 3132 // ----------------------------------- |
| 2951 Label miss; | 3133 Label miss; |
| 2952 | 3134 |
| 2953 // If the object is the holder then we know that it's a global | 3135 // If the object is the holder then we know that it's a global |
| 2954 // object which can only happen for contextual loads. In this case, | 3136 // object which can only happen for contextual loads. In this case, |
| 2955 // the receiver cannot be a smi. | 3137 // the receiver cannot be a smi. |
| 2956 if (object != holder) { | 3138 if (!object.is_identical_to(holder)) { |
| 2957 __ JumpIfSmi(eax, &miss); | 3139 __ JumpIfSmi(eax, &miss); |
| 2958 } | 3140 } |
| 2959 | 3141 |
| 2960 // Check that the maps haven't changed. | 3142 // Check that the maps haven't changed. |
| 2961 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 3143 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
| 2962 | 3144 |
| 2963 // Get the value from the cell. | 3145 // Get the value from the cell. |
| 2964 if (Serializer::enabled()) { | 3146 if (Serializer::enabled()) { |
| 2965 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 3147 __ mov(ebx, Immediate(cell)); |
| 2966 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 3148 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| 2967 } else { | 3149 } else { |
| 2968 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 3150 __ mov(ebx, Operand::Cell(cell)); |
| 2969 } | 3151 } |
| 2970 | 3152 |
| 2971 // Check for deleted property if property can actually be deleted. | 3153 // Check for deleted property if property can actually be deleted. |
| 2972 if (!is_dont_delete) { | 3154 if (!is_dont_delete) { |
| 2973 __ cmp(ebx, factory()->the_hole_value()); | 3155 __ cmp(ebx, factory()->the_hole_value()); |
| 2974 __ j(equal, &miss); | 3156 __ j(equal, &miss); |
| 2975 } else if (FLAG_debug_code) { | 3157 } else if (FLAG_debug_code) { |
| 2976 __ cmp(ebx, factory()->the_hole_value()); | 3158 __ cmp(ebx, factory()->the_hole_value()); |
| 2977 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3159 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 2978 } | 3160 } |
| 2979 | 3161 |
| 2980 Counters* counters = isolate()->counters(); | 3162 Counters* counters = isolate()->counters(); |
| 2981 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3163 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 2982 __ mov(eax, ebx); | 3164 __ mov(eax, ebx); |
| 2983 __ ret(0); | 3165 __ ret(0); |
| 2984 | 3166 |
| 2985 __ bind(&miss); | 3167 __ bind(&miss); |
| 2986 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); | 3168 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); |
| 2987 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3169 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2988 | 3170 |
| 2989 // Return the generated code. | 3171 // Return the generated code. |
| 2990 return GetCode(NORMAL, name); | 3172 return GetCode(NORMAL, name); |
| 2991 } | 3173 } |
| 2992 | 3174 |
| 2993 | 3175 |
| 2994 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 3176 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
| 2995 JSObject* receiver, | 3177 Handle<JSObject> receiver, |
| 2996 JSObject* holder, | 3178 Handle<JSObject> holder, |
| 2997 int index) { | 3179 int index) { |
| 2998 // ----------- S t a t e ------------- | 3180 // ----------- S t a t e ------------- |
| 2999 // -- eax : key | 3181 // -- eax : key |
| 3000 // -- edx : receiver | 3182 // -- edx : receiver |
| 3001 // -- esp[0] : return address | 3183 // -- esp[0] : return address |
| 3002 // ----------------------------------- | 3184 // ----------------------------------- |
| 3003 Label miss; | 3185 Label miss; |
| 3004 | 3186 |
| 3005 Counters* counters = isolate()->counters(); | 3187 Counters* counters = isolate()->counters(); |
| 3006 __ IncrementCounter(counters->keyed_load_field(), 1); | 3188 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 3007 | 3189 |
| 3008 // Check that the name has not changed. | 3190 // Check that the name has not changed. |
| 3009 __ cmp(eax, Immediate(Handle<String>(name))); | 3191 __ cmp(eax, Immediate(name)); |
| 3010 __ j(not_equal, &miss); | 3192 __ j(not_equal, &miss); |
| 3011 | 3193 |
| 3012 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 3194 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 3013 | 3195 |
| 3014 __ bind(&miss); | 3196 __ bind(&miss); |
| 3015 __ DecrementCounter(counters->keyed_load_field(), 1); | 3197 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 3016 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3198 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3017 | 3199 |
| 3018 // Return the generated code. | 3200 // Return the generated code. |
| 3019 return GetCode(FIELD, name); | 3201 return GetCode(FIELD, name); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3045 miss.Unuse(); | 3227 miss.Unuse(); |
| 3046 return result; | 3228 return result; |
| 3047 } | 3229 } |
| 3048 | 3230 |
| 3049 __ bind(&miss); | 3231 __ bind(&miss); |
| 3050 | 3232 |
| 3051 __ DecrementCounter(counters->keyed_load_callback(), 1); | 3233 __ DecrementCounter(counters->keyed_load_callback(), 1); |
| 3052 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3234 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3053 | 3235 |
| 3054 // Return the generated code. | 3236 // Return the generated code. |
| 3055 return GetCode(CALLBACKS, name); | 3237 return TryGetCode(CALLBACKS, name); |
| 3056 } | 3238 } |
| 3057 | 3239 |
| 3058 | 3240 |
| 3059 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 3241 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 3060 JSObject* receiver, | 3242 Handle<String> name, |
| 3061 JSObject* holder, | 3243 Handle<JSObject> receiver, |
| 3062 Object* value) { | 3244 Handle<JSObject> holder, |
| 3245 Handle<Object> value) { |
| 3063 // ----------- S t a t e ------------- | 3246 // ----------- S t a t e ------------- |
| 3064 // -- eax : key | 3247 // -- eax : key |
| 3065 // -- edx : receiver | 3248 // -- edx : receiver |
| 3066 // -- esp[0] : return address | 3249 // -- esp[0] : return address |
| 3067 // ----------------------------------- | 3250 // ----------------------------------- |
| 3068 Label miss; | 3251 Label miss; |
| 3069 | 3252 |
| 3070 Counters* counters = isolate()->counters(); | 3253 Counters* counters = isolate()->counters(); |
| 3071 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 3254 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 3072 | 3255 |
| 3073 // Check that the name has not changed. | 3256 // Check that the name has not changed. |
| 3074 __ cmp(eax, Immediate(Handle<String>(name))); | 3257 __ cmp(eax, Immediate(name)); |
| 3075 __ j(not_equal, &miss); | 3258 __ j(not_equal, &miss); |
| 3076 | 3259 |
| 3077 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 3260 GenerateLoadConstant( |
| 3078 value, name, &miss); | 3261 receiver, holder, edx, ebx, ecx, edi, value, name, &miss); |
| 3079 __ bind(&miss); | 3262 __ bind(&miss); |
| 3080 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 3263 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3264 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3082 | 3265 |
| 3083 // Return the generated code. | 3266 // Return the generated code. |
| 3084 return GetCode(CONSTANT_FUNCTION, name); | 3267 return GetCode(CONSTANT_FUNCTION, name); |
| 3085 } | 3268 } |
| 3086 | 3269 |
| 3087 | 3270 |
| 3088 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3271 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 3089 JSObject* holder, | 3272 JSObject* holder, |
| 3090 String* name) { | 3273 String* name) { |
| 3091 // ----------- S t a t e ------------- | 3274 // ----------- S t a t e ------------- |
| 3092 // -- eax : key | 3275 // -- eax : key |
| 3093 // -- edx : receiver | 3276 // -- edx : receiver |
| 3094 // -- esp[0] : return address | 3277 // -- esp[0] : return address |
| 3095 // ----------------------------------- | 3278 // ----------------------------------- |
| 3096 Label miss; | 3279 Label miss; |
| 3097 | 3280 |
| 3098 Counters* counters = isolate()->counters(); | 3281 Counters* counters = isolate()->counters(); |
| 3099 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3282 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 3100 | 3283 |
| 3101 // Check that the name has not changed. | 3284 // Check that the name has not changed. |
| 3102 __ cmp(eax, Immediate(Handle<String>(name))); | 3285 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3103 __ j(not_equal, &miss); | 3286 __ j(not_equal, &miss); |
| 3104 | 3287 |
| 3105 LookupResult lookup; | 3288 LookupResult lookup(isolate()); |
| 3106 LookupPostInterceptor(holder, name, &lookup); | 3289 LookupPostInterceptor(holder, name, &lookup); |
| 3107 GenerateLoadInterceptor(receiver, | 3290 GenerateLoadInterceptor(receiver, |
| 3108 holder, | 3291 holder, |
| 3109 &lookup, | 3292 &lookup, |
| 3110 edx, | 3293 edx, |
| 3111 eax, | 3294 eax, |
| 3112 ecx, | 3295 ecx, |
| 3113 ebx, | 3296 ebx, |
| 3114 edi, | 3297 edi, |
| 3115 name, | 3298 name, |
| 3116 &miss); | 3299 &miss); |
| 3117 __ bind(&miss); | 3300 __ bind(&miss); |
| 3118 __ DecrementCounter(counters->keyed_load_interceptor(), 1); | 3301 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
| 3119 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3302 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3120 | 3303 |
| 3121 // Return the generated code. | 3304 // Return the generated code. |
| 3122 return GetCode(INTERCEPTOR, name); | 3305 return TryGetCode(INTERCEPTOR, name); |
| 3123 } | 3306 } |
| 3124 | 3307 |
| 3125 | 3308 |
| 3126 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3309 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3310 Handle<String> name) { |
| 3127 // ----------- S t a t e ------------- | 3311 // ----------- S t a t e ------------- |
| 3128 // -- eax : key | 3312 // -- eax : key |
| 3129 // -- edx : receiver | 3313 // -- edx : receiver |
| 3130 // -- esp[0] : return address | 3314 // -- esp[0] : return address |
| 3131 // ----------------------------------- | 3315 // ----------------------------------- |
| 3132 Label miss; | 3316 Label miss; |
| 3133 | 3317 |
| 3134 Counters* counters = isolate()->counters(); | 3318 Counters* counters = isolate()->counters(); |
| 3135 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3319 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 3136 | 3320 |
| 3137 // Check that the name has not changed. | 3321 // Check that the name has not changed. |
| 3138 __ cmp(eax, Immediate(Handle<String>(name))); | 3322 __ cmp(eax, Immediate(name)); |
| 3139 __ j(not_equal, &miss); | 3323 __ j(not_equal, &miss); |
| 3140 | 3324 |
| 3141 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3325 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
| 3142 __ bind(&miss); | 3326 __ bind(&miss); |
| 3143 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3327 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 3144 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3328 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3145 | 3329 |
| 3146 // Return the generated code. | 3330 // Return the generated code. |
| 3147 return GetCode(CALLBACKS, name); | 3331 return GetCode(CALLBACKS, name); |
| 3148 } | 3332 } |
| 3149 | 3333 |
| 3150 | 3334 |
| 3151 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3335 Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
| 3336 Handle<String> name) { |
| 3152 // ----------- S t a t e ------------- | 3337 // ----------- S t a t e ------------- |
| 3153 // -- eax : key | 3338 // -- eax : key |
| 3154 // -- edx : receiver | 3339 // -- edx : receiver |
| 3155 // -- esp[0] : return address | 3340 // -- esp[0] : return address |
| 3156 // ----------------------------------- | 3341 // ----------------------------------- |
| 3157 Label miss; | 3342 Label miss; |
| 3158 | 3343 |
| 3159 Counters* counters = isolate()->counters(); | 3344 Counters* counters = isolate()->counters(); |
| 3160 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3345 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3161 | 3346 |
| 3162 // Check that the name has not changed. | 3347 // Check that the name has not changed. |
| 3163 __ cmp(eax, Immediate(Handle<String>(name))); | 3348 __ cmp(eax, Immediate(name)); |
| 3164 __ j(not_equal, &miss); | 3349 __ j(not_equal, &miss); |
| 3165 | 3350 |
| 3166 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3351 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
| 3167 __ bind(&miss); | 3352 __ bind(&miss); |
| 3168 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3353 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3169 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3354 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3170 | 3355 |
| 3171 // Return the generated code. | 3356 // Return the generated code. |
| 3172 return GetCode(CALLBACKS, name); | 3357 return GetCode(CALLBACKS, name); |
| 3173 } | 3358 } |
| 3174 | 3359 |
| 3175 | 3360 |
| 3176 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3361 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
| 3362 Handle<String> name) { |
| 3177 // ----------- S t a t e ------------- | 3363 // ----------- S t a t e ------------- |
| 3178 // -- eax : key | 3364 // -- eax : key |
| 3179 // -- edx : receiver | 3365 // -- edx : receiver |
| 3180 // -- esp[0] : return address | 3366 // -- esp[0] : return address |
| 3181 // ----------------------------------- | 3367 // ----------------------------------- |
| 3182 Label miss; | 3368 Label miss; |
| 3183 | 3369 |
| 3184 Counters* counters = isolate()->counters(); | 3370 Counters* counters = isolate()->counters(); |
| 3185 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3371 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3186 | 3372 |
| 3187 // Check that the name has not changed. | 3373 // Check that the name has not changed. |
| 3188 __ cmp(eax, Immediate(Handle<String>(name))); | 3374 __ cmp(eax, Immediate(name)); |
| 3189 __ j(not_equal, &miss); | 3375 __ j(not_equal, &miss); |
| 3190 | 3376 |
| 3191 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3377 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
| 3192 __ bind(&miss); | 3378 __ bind(&miss); |
| 3193 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3379 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3194 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3380 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3195 | 3381 |
| 3196 // Return the generated code. | 3382 // Return the generated code. |
| 3197 return GetCode(CALLBACKS, name); | 3383 return GetCode(CALLBACKS, name); |
| 3198 } | 3384 } |
| 3199 | 3385 |
| 3200 | 3386 |
| 3201 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { | 3387 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 3388 Handle<Map> receiver_map) { |
| 3202 // ----------- S t a t e ------------- | 3389 // ----------- S t a t e ------------- |
| 3203 // -- eax : key | 3390 // -- eax : key |
| 3204 // -- edx : receiver | 3391 // -- edx : receiver |
| 3205 // -- esp[0] : return address | 3392 // -- esp[0] : return address |
| 3206 // ----------------------------------- | 3393 // ----------------------------------- |
| 3207 Code* stub; | 3394 |
| 3208 ElementsKind elements_kind = receiver_map->elements_kind(); | 3395 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3209 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); | 3396 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
| 3210 if (!maybe_stub->To(&stub)) return maybe_stub; | 3397 |
| 3211 __ DispatchMap(edx, | 3398 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3212 Handle<Map>(receiver_map), | |
| 3213 Handle<Code>(stub), | |
| 3214 DO_SMI_CHECK); | |
| 3215 | 3399 |
| 3216 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3400 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3217 | 3401 |
| 3218 // Return the generated code. | 3402 // Return the generated code. |
| 3219 return GetCode(NORMAL, NULL); | 3403 return GetCode(NORMAL, factory()->empty_string()); |
| 3220 } | 3404 } |
| 3221 | 3405 |
| 3222 | 3406 |
| 3223 MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3407 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
| 3224 MapList* receiver_maps, | 3408 MapHandleList* receiver_maps, |
| 3225 CodeList* handler_ics) { | 3409 CodeHandleList* handler_ics) { |
| 3226 // ----------- S t a t e ------------- | 3410 // ----------- S t a t e ------------- |
| 3227 // -- eax : key | 3411 // -- eax : key |
| 3228 // -- edx : receiver | 3412 // -- edx : receiver |
| 3229 // -- esp[0] : return address | 3413 // -- esp[0] : return address |
| 3230 // ----------------------------------- | 3414 // ----------------------------------- |
| 3231 Label miss; | 3415 Label miss; |
| 3232 __ JumpIfSmi(edx, &miss); | 3416 __ JumpIfSmi(edx, &miss); |
| 3233 | 3417 |
| 3234 Register map_reg = ebx; | 3418 Register map_reg = ebx; |
| 3235 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); | 3419 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); |
| 3236 int receiver_count = receiver_maps->length(); | 3420 int receiver_count = receiver_maps->length(); |
| 3237 for (int current = 0; current < receiver_count; ++current) { | 3421 for (int current = 0; current < receiver_count; ++current) { |
| 3238 Handle<Map> map(receiver_maps->at(current)); | 3422 __ cmp(map_reg, receiver_maps->at(current)); |
| 3239 __ cmp(map_reg, map); | 3423 __ j(equal, handler_ics->at(current)); |
| 3240 __ j(equal, Handle<Code>(handler_ics->at(current))); | |
| 3241 } | 3424 } |
| 3242 | 3425 |
| 3243 __ bind(&miss); | 3426 __ bind(&miss); |
| 3244 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3427 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3245 | 3428 |
| 3246 // Return the generated code. | 3429 // Return the generated code. |
| 3247 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 3430 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 3248 } | 3431 } |
| 3249 | 3432 |
| 3250 | 3433 |
| 3251 // Specialized stub for constructing objects from functions which only have only | 3434 // Specialized stub for constructing objects from functions which only have only |
| 3252 // simple assignments of the form this.x = ...; in their body. | 3435 // simple assignments of the form this.x = ...; in their body. |
| 3253 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3436 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| 3254 // ----------- S t a t e ------------- | 3437 // ----------- S t a t e ------------- |
| 3255 // -- eax : argc | 3438 // -- eax : argc |
| 3256 // -- edi : constructor | 3439 // -- edi : constructor |
| 3257 // -- esp[0] : return address | 3440 // -- esp[0] : return address |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4026 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4209 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4027 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 4210 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
| 4028 } | 4211 } |
| 4029 | 4212 |
| 4030 | 4213 |
| 4031 #undef __ | 4214 #undef __ |
| 4032 | 4215 |
| 4033 } } // namespace v8::internal | 4216 } } // namespace v8::internal |
| 4034 | 4217 |
| 4035 #endif // V8_TARGET_ARCH_IA32 | 4218 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |