| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 | 114 |
| 115 // Bail out if the receiver has a named interceptor or requires access checks. | 115 // Bail out if the receiver has a named interceptor or requires access checks. |
| 116 Register map = scratch1; | 116 Register map = scratch1; |
| 117 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 117 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 118 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | 118 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 119 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | 119 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
| 120 __ b(ne, miss_label); | 120 __ b(ne, miss_label); |
| 121 | 121 |
| 122 // Check that receiver is a JSObject. | 122 // Check that receiver is a JSObject. |
| 123 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 123 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 124 __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE)); | 124 __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 125 __ b(lt, miss_label); | 125 __ b(lt, miss_label); |
| 126 | 126 |
| 127 // Load properties array. | 127 // Load properties array. |
| 128 Register properties = scratch0; | 128 Register properties = scratch0; |
| 129 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 129 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 130 // Check that the properties array is a dictionary. | 130 // Check that the properties array is a dictionary. |
| 131 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | 131 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
| 132 Register tmp = properties; | 132 Register tmp = properties; |
| 133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | 133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
| 134 __ cmp(map, tmp); | 134 __ cmp(map, tmp); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 ASSERT(!extra2.is(name)); | 182 ASSERT(!extra2.is(name)); |
| 183 ASSERT(!extra2.is(scratch)); | 183 ASSERT(!extra2.is(scratch)); |
| 184 ASSERT(!extra2.is(extra)); | 184 ASSERT(!extra2.is(extra)); |
| 185 | 185 |
| 186 // Check scratch, extra and extra2 registers are valid. | 186 // Check scratch, extra and extra2 registers are valid. |
| 187 ASSERT(!scratch.is(no_reg)); | 187 ASSERT(!scratch.is(no_reg)); |
| 188 ASSERT(!extra.is(no_reg)); | 188 ASSERT(!extra.is(no_reg)); |
| 189 ASSERT(!extra2.is(no_reg)); | 189 ASSERT(!extra2.is(no_reg)); |
| 190 | 190 |
| 191 // Check that the receiver isn't a smi. | 191 // Check that the receiver isn't a smi. |
| 192 __ tst(receiver, Operand(kSmiTagMask)); | 192 __ JumpIfSmi(receiver, &miss); |
| 193 __ b(eq, &miss); | |
| 194 | 193 |
| 195 // Get the map of the receiver and compute the hash. | 194 // Get the map of the receiver and compute the hash. |
| 196 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); | 195 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); |
| 197 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 196 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 198 __ add(scratch, scratch, Operand(ip)); | 197 __ add(scratch, scratch, Operand(ip)); |
| 199 __ eor(scratch, scratch, Operand(flags)); | 198 __ eor(scratch, scratch, Operand(flags)); |
| 200 __ and_(scratch, | 199 __ and_(scratch, |
| 201 scratch, | 200 scratch, |
| 202 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); | 201 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); |
| 203 | 202 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 __ ldr(dst, FieldMemOperand(dst, offset)); | 274 __ ldr(dst, FieldMemOperand(dst, offset)); |
| 276 } | 275 } |
| 277 } | 276 } |
| 278 | 277 |
| 279 | 278 |
| 280 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 279 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
| 281 Register receiver, | 280 Register receiver, |
| 282 Register scratch, | 281 Register scratch, |
| 283 Label* miss_label) { | 282 Label* miss_label) { |
| 284 // Check that the receiver isn't a smi. | 283 // Check that the receiver isn't a smi. |
| 285 __ tst(receiver, Operand(kSmiTagMask)); | 284 __ JumpIfSmi(receiver, miss_label); |
| 286 __ b(eq, miss_label); | |
| 287 | 285 |
| 288 // Check that the object is a JS array. | 286 // Check that the object is a JS array. |
| 289 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); | 287 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); |
| 290 __ b(ne, miss_label); | 288 __ b(ne, miss_label); |
| 291 | 289 |
| 292 // Load length directly from the JS array. | 290 // Load length directly from the JS array. |
| 293 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 291 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 294 __ Ret(); | 292 __ Ret(); |
| 295 } | 293 } |
| 296 | 294 |
| 297 | 295 |
| 298 // Generate code to check if an object is a string. If the object is a | 296 // Generate code to check if an object is a string. If the object is a |
| 299 // heap object, its map's instance type is left in the scratch1 register. | 297 // heap object, its map's instance type is left in the scratch1 register. |
| 300 // If this is not needed, scratch1 and scratch2 may be the same register. | 298 // If this is not needed, scratch1 and scratch2 may be the same register. |
| 301 static void GenerateStringCheck(MacroAssembler* masm, | 299 static void GenerateStringCheck(MacroAssembler* masm, |
| 302 Register receiver, | 300 Register receiver, |
| 303 Register scratch1, | 301 Register scratch1, |
| 304 Register scratch2, | 302 Register scratch2, |
| 305 Label* smi, | 303 Label* smi, |
| 306 Label* non_string_object) { | 304 Label* non_string_object) { |
| 307 // Check that the receiver isn't a smi. | 305 // Check that the receiver isn't a smi. |
| 308 __ tst(receiver, Operand(kSmiTagMask)); | 306 __ JumpIfSmi(receiver, smi); |
| 309 __ b(eq, smi); | |
| 310 | 307 |
| 311 // Check that the object is a string. | 308 // Check that the object is a string. |
| 312 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 309 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 313 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 310 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 314 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); | 311 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); |
| 315 // The cast is to resolve the overload for the argument of 0x0. | 312 // The cast is to resolve the overload for the argument of 0x0. |
| 316 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); | 313 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); |
| 317 __ b(ne, non_string_object); | 314 __ b(ne, non_string_object); |
| 318 } | 315 } |
| 319 | 316 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 int index, | 371 int index, |
| 375 Map* transition, | 372 Map* transition, |
| 376 Register receiver_reg, | 373 Register receiver_reg, |
| 377 Register name_reg, | 374 Register name_reg, |
| 378 Register scratch, | 375 Register scratch, |
| 379 Label* miss_label) { | 376 Label* miss_label) { |
| 380 // r0 : value | 377 // r0 : value |
| 381 Label exit; | 378 Label exit; |
| 382 | 379 |
| 383 // Check that the receiver isn't a smi. | 380 // Check that the receiver isn't a smi. |
| 384 __ tst(receiver_reg, Operand(kSmiTagMask)); | 381 __ JumpIfSmi(receiver_reg, miss_label); |
| 385 __ b(eq, miss_label); | |
| 386 | 382 |
| 387 // Check that the map of the receiver hasn't changed. | 383 // Check that the map of the receiver hasn't changed. |
| 388 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | 384 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
| 389 __ cmp(scratch, Operand(Handle<Map>(object->map()))); | 385 __ cmp(scratch, Operand(Handle<Map>(object->map()))); |
| 390 __ b(ne, miss_label); | 386 __ b(ne, miss_label); |
| 391 | 387 |
| 392 // Perform global security token check if needed. | 388 // Perform global security token check if needed. |
| 393 if (object->IsJSGlobalProxy()) { | 389 if (object->IsJSGlobalProxy()) { |
| 394 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 390 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 395 } | 391 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 423 // Adjust for the number of properties stored in the object. Even in the | 419 // Adjust for the number of properties stored in the object. Even in the |
| 424 // face of a transition we can use the old map here because the size of the | 420 // face of a transition we can use the old map here because the size of the |
| 425 // object and the number of in-object properties is not going to change. | 421 // object and the number of in-object properties is not going to change. |
| 426 index -= object->map()->inobject_properties(); | 422 index -= object->map()->inobject_properties(); |
| 427 | 423 |
| 428 if (index < 0) { | 424 if (index < 0) { |
| 429 // Set the property straight into the object. | 425 // Set the property straight into the object. |
| 430 int offset = object->map()->instance_size() + (index * kPointerSize); | 426 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 431 __ str(r0, FieldMemOperand(receiver_reg, offset)); | 427 __ str(r0, FieldMemOperand(receiver_reg, offset)); |
| 432 | 428 |
| 429 // Skip updating write barrier if storing a smi. |
| 430 __ JumpIfSmi(r0, &exit); |
| 431 |
| 433 // Update the write barrier for the array address. | 432 // Update the write barrier for the array address. |
| 434 // Pass the now unused name_reg as a scratch register. | 433 // Pass the now unused name_reg as a scratch register. |
| 435 __ mov(name_reg, r0); | 434 __ mov(name_reg, r0); |
| 436 __ RecordWriteField(receiver_reg, | 435 __ RecordWriteField(receiver_reg, |
| 437 offset, | 436 offset, |
| 438 name_reg, | 437 name_reg, |
| 439 scratch, | 438 scratch, |
| 440 kLRHasNotBeenSaved, | 439 kLRHasNotBeenSaved, |
| 441 kDontSaveFPRegs); | 440 kDontSaveFPRegs); |
| 442 } else { | 441 } else { |
| 443 // Write to the properties array. | 442 // Write to the properties array. |
| 444 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 443 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 445 // Get the properties array | 444 // Get the properties array |
| 446 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 445 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 447 __ str(r0, FieldMemOperand(scratch, offset)); | 446 __ str(r0, FieldMemOperand(scratch, offset)); |
| 448 | 447 |
| 448 // Skip updating write barrier if storing a smi. |
| 449 __ JumpIfSmi(r0, &exit); |
| 450 |
| 449 // Update the write barrier for the array address. | 451 // Update the write barrier for the array address. |
| 450 // Ok to clobber receiver_reg and name_reg, since we return. | 452 // Ok to clobber receiver_reg and name_reg, since we return. |
| 451 __ mov(name_reg, r0); | 453 __ mov(name_reg, r0); |
| 452 __ RecordWriteField(scratch, | 454 __ RecordWriteField(scratch, |
| 453 offset, | 455 offset, |
| 454 name_reg, | 456 name_reg, |
| 455 receiver_reg, | 457 receiver_reg, |
| 456 kLRHasNotBeenSaved, | 458 kLRHasNotBeenSaved, |
| 457 kDontSaveFPRegs); | 459 kDontSaveFPRegs); |
| 458 } | 460 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 473 } | 475 } |
| 474 | 476 |
| 475 Handle<Code> ic(code); | 477 Handle<Code> ic(code); |
| 476 __ Jump(ic, RelocInfo::CODE_TARGET); | 478 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 477 } | 479 } |
| 478 | 480 |
| 479 | 481 |
| 480 static void GenerateCallFunction(MacroAssembler* masm, | 482 static void GenerateCallFunction(MacroAssembler* masm, |
| 481 Object* object, | 483 Object* object, |
| 482 const ParameterCount& arguments, | 484 const ParameterCount& arguments, |
| 483 Label* miss) { | 485 Label* miss, |
| 486 Code::ExtraICState extra_ic_state) { |
| 484 // ----------- S t a t e ------------- | 487 // ----------- S t a t e ------------- |
| 485 // -- r0: receiver | 488 // -- r0: receiver |
| 486 // -- r1: function to call | 489 // -- r1: function to call |
| 487 // ----------------------------------- | 490 // ----------------------------------- |
| 488 | 491 |
| 489 // Check that the function really is a function. | 492 // Check that the function really is a function. |
| 490 __ JumpIfSmi(r1, miss); | 493 __ JumpIfSmi(r1, miss); |
| 491 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 494 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 492 __ b(ne, miss); | 495 __ b(ne, miss); |
| 493 | 496 |
| 494 // Patch the receiver on the stack with the global proxy if | 497 // Patch the receiver on the stack with the global proxy if |
| 495 // necessary. | 498 // necessary. |
| 496 if (object->IsGlobalObject()) { | 499 if (object->IsGlobalObject()) { |
| 497 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 500 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
| 498 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); | 501 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); |
| 499 } | 502 } |
| 500 | 503 |
| 501 // Invoke the function. | 504 // Invoke the function. |
| 502 __ InvokeFunction(r1, arguments, JUMP_FUNCTION); | 505 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) |
| 506 ? CALL_AS_FUNCTION |
| 507 : CALL_AS_METHOD; |
| 508 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 503 } | 509 } |
| 504 | 510 |
| 505 | 511 |
| 506 static void PushInterceptorArguments(MacroAssembler* masm, | 512 static void PushInterceptorArguments(MacroAssembler* masm, |
| 507 Register receiver, | 513 Register receiver, |
| 508 Register holder, | 514 Register holder, |
| 509 Register name, | 515 Register name, |
| 510 JSObject* holder_obj) { | 516 JSObject* holder_obj) { |
| 511 __ push(name); | 517 __ push(name); |
| 512 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 518 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 ExternalReference ref = ExternalReference(&fun, | 628 ExternalReference ref = ExternalReference(&fun, |
| 623 ExternalReference::DIRECT_API_CALL, | 629 ExternalReference::DIRECT_API_CALL, |
| 624 masm->isolate()); | 630 masm->isolate()); |
| 625 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 631 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 626 } | 632 } |
| 627 | 633 |
| 628 class CallInterceptorCompiler BASE_EMBEDDED { | 634 class CallInterceptorCompiler BASE_EMBEDDED { |
| 629 public: | 635 public: |
| 630 CallInterceptorCompiler(StubCompiler* stub_compiler, | 636 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 631 const ParameterCount& arguments, | 637 const ParameterCount& arguments, |
| 632 Register name) | 638 Register name, |
| 639 Code::ExtraICState extra_ic_state) |
| 633 : stub_compiler_(stub_compiler), | 640 : stub_compiler_(stub_compiler), |
| 634 arguments_(arguments), | 641 arguments_(arguments), |
| 635 name_(name) {} | 642 name_(name), |
| 643 extra_ic_state_(extra_ic_state) {} |
| 636 | 644 |
| 637 MaybeObject* Compile(MacroAssembler* masm, | 645 MaybeObject* Compile(MacroAssembler* masm, |
| 638 JSObject* object, | 646 JSObject* object, |
| 639 JSObject* holder, | 647 JSObject* holder, |
| 640 String* name, | 648 String* name, |
| 641 LookupResult* lookup, | 649 LookupResult* lookup, |
| 642 Register receiver, | 650 Register receiver, |
| 643 Register scratch1, | 651 Register scratch1, |
| 644 Register scratch2, | 652 Register scratch2, |
| 645 Register scratch3, | 653 Register scratch3, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 ASSERT(depth2 == kInvalidProtoDepth); | 761 ASSERT(depth2 == kInvalidProtoDepth); |
| 754 } | 762 } |
| 755 | 763 |
| 756 // Invoke function. | 764 // Invoke function. |
| 757 if (can_do_fast_api_call) { | 765 if (can_do_fast_api_call) { |
| 758 MaybeObject* result = GenerateFastApiDirectCall(masm, | 766 MaybeObject* result = GenerateFastApiDirectCall(masm, |
| 759 optimization, | 767 optimization, |
| 760 arguments_.immediate()); | 768 arguments_.immediate()); |
| 761 if (result->IsFailure()) return result; | 769 if (result->IsFailure()) return result; |
| 762 } else { | 770 } else { |
| 771 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 772 ? CALL_AS_FUNCTION |
| 773 : CALL_AS_METHOD; |
| 763 __ InvokeFunction(optimization.constant_function(), arguments_, | 774 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 764 JUMP_FUNCTION); | 775 JUMP_FUNCTION, call_kind); |
| 765 } | 776 } |
| 766 | 777 |
| 767 // Deferred code for fast API call case---clean preallocated space. | 778 // Deferred code for fast API call case---clean preallocated space. |
| 768 if (can_do_fast_api_call) { | 779 if (can_do_fast_api_call) { |
| 769 __ bind(&miss_cleanup); | 780 __ bind(&miss_cleanup); |
| 770 FreeSpaceForFastApiCall(masm); | 781 FreeSpaceForFastApiCall(masm); |
| 771 __ b(miss_label); | 782 __ b(miss_label); |
| 772 } | 783 } |
| 773 | 784 |
| 774 // Invoke a regular function. | 785 // Invoke a regular function. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 | 847 |
| 837 // If interceptor returns no-result sentinel, call the constant function. | 848 // If interceptor returns no-result sentinel, call the constant function. |
| 838 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 849 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 839 __ cmp(r0, scratch); | 850 __ cmp(r0, scratch); |
| 840 __ b(ne, interceptor_succeeded); | 851 __ b(ne, interceptor_succeeded); |
| 841 } | 852 } |
| 842 | 853 |
| 843 StubCompiler* stub_compiler_; | 854 StubCompiler* stub_compiler_; |
| 844 const ParameterCount& arguments_; | 855 const ParameterCount& arguments_; |
| 845 Register name_; | 856 Register name_; |
| 857 Code::ExtraICState extra_ic_state_; |
| 846 }; | 858 }; |
| 847 | 859 |
| 848 | 860 |
| 849 // Generate code to check that a global property cell is empty. Create | 861 // Generate code to check that a global property cell is empty. Create |
| 850 // the property cell at compilation time if no cell exists for the | 862 // the property cell at compilation time if no cell exists for the |
| 851 // property. | 863 // property. |
| 852 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 864 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( |
| 853 MacroAssembler* masm, | 865 MacroAssembler* masm, |
| 854 GlobalObject* global, | 866 GlobalObject* global, |
| 855 String* name, | 867 String* name, |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 void StubCompiler::GenerateLoadField(JSObject* object, | 1164 void StubCompiler::GenerateLoadField(JSObject* object, |
| 1153 JSObject* holder, | 1165 JSObject* holder, |
| 1154 Register receiver, | 1166 Register receiver, |
| 1155 Register scratch1, | 1167 Register scratch1, |
| 1156 Register scratch2, | 1168 Register scratch2, |
| 1157 Register scratch3, | 1169 Register scratch3, |
| 1158 int index, | 1170 int index, |
| 1159 String* name, | 1171 String* name, |
| 1160 Label* miss) { | 1172 Label* miss) { |
| 1161 // Check that the receiver isn't a smi. | 1173 // Check that the receiver isn't a smi. |
| 1162 __ tst(receiver, Operand(kSmiTagMask)); | 1174 __ JumpIfSmi(receiver, miss); |
| 1163 __ b(eq, miss); | |
| 1164 | 1175 |
| 1165 // Check that the maps haven't changed. | 1176 // Check that the maps haven't changed. |
| 1166 Register reg = | 1177 Register reg = |
| 1167 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1178 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 1168 name, miss); | 1179 name, miss); |
| 1169 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); | 1180 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); |
| 1170 __ Ret(); | 1181 __ Ret(); |
| 1171 } | 1182 } |
| 1172 | 1183 |
| 1173 | 1184 |
| 1174 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1185 void StubCompiler::GenerateLoadConstant(JSObject* object, |
| 1175 JSObject* holder, | 1186 JSObject* holder, |
| 1176 Register receiver, | 1187 Register receiver, |
| 1177 Register scratch1, | 1188 Register scratch1, |
| 1178 Register scratch2, | 1189 Register scratch2, |
| 1179 Register scratch3, | 1190 Register scratch3, |
| 1180 Object* value, | 1191 Object* value, |
| 1181 String* name, | 1192 String* name, |
| 1182 Label* miss) { | 1193 Label* miss) { |
| 1183 // Check that the receiver isn't a smi. | 1194 // Check that the receiver isn't a smi. |
| 1184 __ tst(receiver, Operand(kSmiTagMask)); | 1195 __ JumpIfSmi(receiver, miss); |
| 1185 __ b(eq, miss); | |
| 1186 | 1196 |
| 1187 // Check that the maps haven't changed. | 1197 // Check that the maps haven't changed. |
| 1188 Register reg = | 1198 Register reg = |
| 1189 CheckPrototypes(object, receiver, holder, | 1199 CheckPrototypes(object, receiver, holder, |
| 1190 scratch1, scratch2, scratch3, name, miss); | 1200 scratch1, scratch2, scratch3, name, miss); |
| 1191 | 1201 |
| 1192 // Return the constant value. | 1202 // Return the constant value. |
| 1193 __ mov(r0, Operand(Handle<Object>(value))); | 1203 __ mov(r0, Operand(Handle<Object>(value))); |
| 1194 __ Ret(); | 1204 __ Ret(); |
| 1195 } | 1205 } |
| 1196 | 1206 |
| 1197 | 1207 |
| 1198 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1208 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1199 JSObject* holder, | 1209 JSObject* holder, |
| 1200 Register receiver, | 1210 Register receiver, |
| 1201 Register name_reg, | 1211 Register name_reg, |
| 1202 Register scratch1, | 1212 Register scratch1, |
| 1203 Register scratch2, | 1213 Register scratch2, |
| 1204 Register scratch3, | 1214 Register scratch3, |
| 1205 AccessorInfo* callback, | 1215 AccessorInfo* callback, |
| 1206 String* name, | 1216 String* name, |
| 1207 Label* miss) { | 1217 Label* miss) { |
| 1208 // Check that the receiver isn't a smi. | 1218 // Check that the receiver isn't a smi. |
| 1209 __ tst(receiver, Operand(kSmiTagMask)); | 1219 __ JumpIfSmi(receiver, miss); |
| 1210 __ b(eq, miss); | |
| 1211 | 1220 |
| 1212 // Check that the maps haven't changed. | 1221 // Check that the maps haven't changed. |
| 1213 Register reg = | 1222 Register reg = |
| 1214 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1223 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 1215 name, miss); | 1224 name, miss); |
| 1216 | 1225 |
| 1217 // Build AccessorInfo::args_ list on the stack and push property name below | 1226 // Build AccessorInfo::args_ list on the stack and push property name below |
| 1218 // the exit frame to make GC aware of them and store pointers to them. | 1227 // the exit frame to make GC aware of them and store pointers to them. |
| 1219 __ push(receiver); | 1228 __ push(receiver); |
| 1220 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ | 1229 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 // Get the number of arguments. | 1422 // Get the number of arguments. |
| 1414 const int argc = arguments().immediate(); | 1423 const int argc = arguments().immediate(); |
| 1415 | 1424 |
| 1416 // Get the receiver from the stack. | 1425 // Get the receiver from the stack. |
| 1417 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1426 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1418 | 1427 |
| 1419 // If the object is the holder then we know that it's a global | 1428 // If the object is the holder then we know that it's a global |
| 1420 // object which can only happen for contextual calls. In this case, | 1429 // object which can only happen for contextual calls. In this case, |
| 1421 // the receiver cannot be a smi. | 1430 // the receiver cannot be a smi. |
| 1422 if (object != holder) { | 1431 if (object != holder) { |
| 1423 __ tst(r0, Operand(kSmiTagMask)); | 1432 __ JumpIfSmi(r0, miss); |
| 1424 __ b(eq, miss); | |
| 1425 } | 1433 } |
| 1426 | 1434 |
| 1427 // Check that the maps haven't changed. | 1435 // Check that the maps haven't changed. |
| 1428 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); | 1436 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); |
| 1429 } | 1437 } |
| 1430 | 1438 |
| 1431 | 1439 |
| 1432 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1440 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, |
| 1433 JSFunction* function, | 1441 JSFunction* function, |
| 1434 Label* miss) { | 1442 Label* miss) { |
| 1435 // Get the value from the cell. | 1443 // Get the value from the cell. |
| 1436 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1444 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
| 1437 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 1445 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
| 1438 | 1446 |
| 1439 // Check that the cell contains the same function. | 1447 // Check that the cell contains the same function. |
| 1440 if (heap()->InNewSpace(function)) { | 1448 if (heap()->InNewSpace(function)) { |
| 1441 // We can't embed a pointer to a function in new space so we have | 1449 // We can't embed a pointer to a function in new space so we have |
| 1442 // to verify that the shared function info is unchanged. This has | 1450 // to verify that the shared function info is unchanged. This has |
| 1443 // the nice side effect that multiple closures based on the same | 1451 // the nice side effect that multiple closures based on the same |
| 1444 // function can all use this call IC. Before we load through the | 1452 // function can all use this call IC. Before we load through the |
| 1445 // function, we have to verify that it still is a function. | 1453 // function, we have to verify that it still is a function. |
| 1446 __ tst(r1, Operand(kSmiTagMask)); | 1454 __ JumpIfSmi(r1, miss); |
| 1447 __ b(eq, miss); | |
| 1448 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 1455 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 1449 __ b(ne, miss); | 1456 __ b(ne, miss); |
| 1450 | 1457 |
| 1451 // Check the shared function info. Make sure it hasn't changed. | 1458 // Check the shared function info. Make sure it hasn't changed. |
| 1452 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1459 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
| 1453 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1460 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1454 __ cmp(r4, r3); | 1461 __ cmp(r4, r3); |
| 1455 __ b(ne, miss); | 1462 __ b(ne, miss); |
| 1456 } else { | 1463 } else { |
| 1457 __ cmp(r1, Operand(Handle<JSFunction>(function))); | 1464 __ cmp(r1, Operand(Handle<JSFunction>(function))); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1482 // ----------------------------------- | 1489 // ----------------------------------- |
| 1483 Label miss; | 1490 Label miss; |
| 1484 | 1491 |
| 1485 GenerateNameCheck(name, &miss); | 1492 GenerateNameCheck(name, &miss); |
| 1486 | 1493 |
| 1487 const int argc = arguments().immediate(); | 1494 const int argc = arguments().immediate(); |
| 1488 | 1495 |
| 1489 // Get the receiver of the function from the stack into r0. | 1496 // Get the receiver of the function from the stack into r0. |
| 1490 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1497 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 1491 // Check that the receiver isn't a smi. | 1498 // Check that the receiver isn't a smi. |
| 1492 __ tst(r0, Operand(kSmiTagMask)); | 1499 __ JumpIfSmi(r0, &miss); |
| 1493 __ b(eq, &miss); | |
| 1494 | 1500 |
| 1495 // Do the right check and compute the holder register. | 1501 // Do the right check and compute the holder register. |
| 1496 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); | 1502 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); |
| 1497 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); | 1503 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); |
| 1498 | 1504 |
| 1499 GenerateCallFunction(masm(), object, arguments(), &miss); | 1505 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); |
| 1500 | 1506 |
| 1501 // Handle call cache miss. | 1507 // Handle call cache miss. |
| 1502 __ bind(&miss); | 1508 __ bind(&miss); |
| 1503 MaybeObject* maybe_result = GenerateMissBranch(); | 1509 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1504 if (maybe_result->IsFailure()) return maybe_result; | 1510 if (maybe_result->IsFailure()) return maybe_result; |
| 1505 | 1511 |
| 1506 // Return the generated code. | 1512 // Return the generated code. |
| 1507 return GetCode(FIELD, name); | 1513 return GetCode(FIELD, name); |
| 1508 } | 1514 } |
| 1509 | 1515 |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 // arguments, bail out to the regular call. | 1966 // arguments, bail out to the regular call. |
| 1961 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1967 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 1962 | 1968 |
| 1963 Label miss; | 1969 Label miss; |
| 1964 GenerateNameCheck(name, &miss); | 1970 GenerateNameCheck(name, &miss); |
| 1965 | 1971 |
| 1966 if (cell == NULL) { | 1972 if (cell == NULL) { |
| 1967 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 1973 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 1968 | 1974 |
| 1969 STATIC_ASSERT(kSmiTag == 0); | 1975 STATIC_ASSERT(kSmiTag == 0); |
| 1970 __ tst(r1, Operand(kSmiTagMask)); | 1976 __ JumpIfSmi(r1, &miss); |
| 1971 __ b(eq, &miss); | |
| 1972 | 1977 |
| 1973 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 1978 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 1974 &miss); | 1979 &miss); |
| 1975 } else { | 1980 } else { |
| 1976 ASSERT(cell->value() == function); | 1981 ASSERT(cell->value() == function); |
| 1977 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1982 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
| 1978 GenerateLoadFunctionFromCell(cell, function, &miss); | 1983 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1979 } | 1984 } |
| 1980 | 1985 |
| 1981 // Load the char code argument. | 1986 // Load the char code argument. |
| 1982 Register code = r1; | 1987 Register code = r1; |
| 1983 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); | 1988 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); |
| 1984 | 1989 |
| 1985 // Check the code is a smi. | 1990 // Check the code is a smi. |
| 1986 Label slow; | 1991 Label slow; |
| 1987 STATIC_ASSERT(kSmiTag == 0); | 1992 STATIC_ASSERT(kSmiTag == 0); |
| 1988 __ tst(code, Operand(kSmiTagMask)); | 1993 __ JumpIfNotSmi(code, &slow); |
| 1989 __ b(ne, &slow); | |
| 1990 | 1994 |
| 1991 // Convert the smi code to uint16. | 1995 // Convert the smi code to uint16. |
| 1992 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 1996 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
| 1993 | 1997 |
| 1994 StringCharFromCodeGenerator char_from_code_generator(code, r0); | 1998 StringCharFromCodeGenerator char_from_code_generator(code, r0); |
| 1995 char_from_code_generator.GenerateFast(masm()); | 1999 char_from_code_generator.GenerateFast(masm()); |
| 1996 __ Drop(argc + 1); | 2000 __ Drop(argc + 1); |
| 1997 __ Ret(); | 2001 __ Ret(); |
| 1998 | 2002 |
| 1999 StubRuntimeCallHelper call_helper; | 2003 StubRuntimeCallHelper call_helper; |
| 2000 char_from_code_generator.GenerateSlow(masm(), call_helper); | 2004 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 2001 | 2005 |
| 2002 // Tail call the full function. We do not have to patch the receiver | 2006 // Tail call the full function. We do not have to patch the receiver |
| 2003 // because the function makes no use of it. | 2007 // because the function makes no use of it. |
| 2004 __ bind(&slow); | 2008 __ bind(&slow); |
| 2005 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2009 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2006 | 2010 |
| 2007 __ bind(&miss); | 2011 __ bind(&miss); |
| 2008 // r2: function name. | 2012 // r2: function name. |
| 2009 MaybeObject* maybe_result = GenerateMissBranch(); | 2013 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2010 if (maybe_result->IsFailure()) return maybe_result; | 2014 if (maybe_result->IsFailure()) return maybe_result; |
| 2011 | 2015 |
| 2012 // Return the generated code. | 2016 // Return the generated code. |
| 2013 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2017 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2014 } | 2018 } |
| 2015 | 2019 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2143 __ Drop(argc + 1); | 2147 __ Drop(argc + 1); |
| 2144 __ Ret(); | 2148 __ Ret(); |
| 2145 | 2149 |
| 2146 __ bind(&wont_fit_smi); | 2150 __ bind(&wont_fit_smi); |
| 2147 // Restore FPCSR and fall to slow case. | 2151 // Restore FPCSR and fall to slow case. |
| 2148 __ vmsr(r3); | 2152 __ vmsr(r3); |
| 2149 | 2153 |
| 2150 __ bind(&slow); | 2154 __ bind(&slow); |
| 2151 // Tail call the full function. We do not have to patch the receiver | 2155 // Tail call the full function. We do not have to patch the receiver |
| 2152 // because the function makes no use of it. | 2156 // because the function makes no use of it. |
| 2153 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2157 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2154 | 2158 |
| 2155 __ bind(&miss); | 2159 __ bind(&miss); |
| 2156 // r2: function name. | 2160 // r2: function name. |
| 2157 MaybeObject* maybe_result = GenerateMissBranch(); | 2161 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2158 if (maybe_result->IsFailure()) return maybe_result; | 2162 if (maybe_result->IsFailure()) return maybe_result; |
| 2159 | 2163 |
| 2160 // Return the generated code. | 2164 // Return the generated code. |
| 2161 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2165 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2162 } | 2166 } |
| 2163 | 2167 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2181 // arguments, bail out to the regular call. | 2185 // arguments, bail out to the regular call. |
| 2182 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2186 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); |
| 2183 | 2187 |
| 2184 Label miss; | 2188 Label miss; |
| 2185 GenerateNameCheck(name, &miss); | 2189 GenerateNameCheck(name, &miss); |
| 2186 | 2190 |
| 2187 if (cell == NULL) { | 2191 if (cell == NULL) { |
| 2188 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2192 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
| 2189 | 2193 |
| 2190 STATIC_ASSERT(kSmiTag == 0); | 2194 STATIC_ASSERT(kSmiTag == 0); |
| 2191 __ tst(r1, Operand(kSmiTagMask)); | 2195 __ JumpIfSmi(r1, &miss); |
| 2192 __ b(eq, &miss); | |
| 2193 | 2196 |
| 2194 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2197 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 2195 &miss); | 2198 &miss); |
| 2196 } else { | 2199 } else { |
| 2197 ASSERT(cell->value() == function); | 2200 ASSERT(cell->value() == function); |
| 2198 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 2201 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
| 2199 GenerateLoadFunctionFromCell(cell, function, &miss); | 2202 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2200 } | 2203 } |
| 2201 | 2204 |
| 2202 // Load the (only) argument into r0. | 2205 // Load the (only) argument into r0. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2245 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 2248 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 2246 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); | 2249 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); |
| 2247 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 2250 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 2248 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2251 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 2249 __ Drop(argc + 1); | 2252 __ Drop(argc + 1); |
| 2250 __ Ret(); | 2253 __ Ret(); |
| 2251 | 2254 |
| 2252 // Tail call the full function. We do not have to patch the receiver | 2255 // Tail call the full function. We do not have to patch the receiver |
| 2253 // because the function makes no use of it. | 2256 // because the function makes no use of it. |
| 2254 __ bind(&slow); | 2257 __ bind(&slow); |
| 2255 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2258 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2256 | 2259 |
| 2257 __ bind(&miss); | 2260 __ bind(&miss); |
| 2258 // r2: function name. | 2261 // r2: function name. |
| 2259 MaybeObject* maybe_result = GenerateMissBranch(); | 2262 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2260 if (maybe_result->IsFailure()) return maybe_result; | 2263 if (maybe_result->IsFailure()) return maybe_result; |
| 2261 | 2264 |
| 2262 // Return the generated code. | 2265 // Return the generated code. |
| 2263 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2266 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2264 } | 2267 } |
| 2265 | 2268 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2285 | 2288 |
| 2286 Label miss, miss_before_stack_reserved; | 2289 Label miss, miss_before_stack_reserved; |
| 2287 | 2290 |
| 2288 GenerateNameCheck(name, &miss_before_stack_reserved); | 2291 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2289 | 2292 |
| 2290 // Get the receiver from the stack. | 2293 // Get the receiver from the stack. |
| 2291 const int argc = arguments().immediate(); | 2294 const int argc = arguments().immediate(); |
| 2292 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2295 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2293 | 2296 |
| 2294 // Check that the receiver isn't a smi. | 2297 // Check that the receiver isn't a smi. |
| 2295 __ tst(r1, Operand(kSmiTagMask)); | 2298 __ JumpIfSmi(r1, &miss_before_stack_reserved); |
| 2296 __ b(eq, &miss_before_stack_reserved); | |
| 2297 | 2299 |
| 2298 __ IncrementCounter(counters->call_const(), 1, r0, r3); | 2300 __ IncrementCounter(counters->call_const(), 1, r0, r3); |
| 2299 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); | 2301 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); |
| 2300 | 2302 |
| 2301 ReserveSpaceForFastApiCall(masm(), r0); | 2303 ReserveSpaceForFastApiCall(masm(), r0); |
| 2302 | 2304 |
| 2303 // Check that the maps haven't changed and find a Holder as a side effect. | 2305 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2304 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2306 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
| 2305 depth, &miss); | 2307 depth, &miss); |
| 2306 | 2308 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 Label miss; | 2342 Label miss; |
| 2341 | 2343 |
| 2342 GenerateNameCheck(name, &miss); | 2344 GenerateNameCheck(name, &miss); |
| 2343 | 2345 |
| 2344 // Get the receiver from the stack | 2346 // Get the receiver from the stack |
| 2345 const int argc = arguments().immediate(); | 2347 const int argc = arguments().immediate(); |
| 2346 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2348 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2347 | 2349 |
| 2348 // Check that the receiver isn't a smi. | 2350 // Check that the receiver isn't a smi. |
| 2349 if (check != NUMBER_CHECK) { | 2351 if (check != NUMBER_CHECK) { |
| 2350 __ tst(r1, Operand(kSmiTagMask)); | 2352 __ JumpIfSmi(r1, &miss); |
| 2351 __ b(eq, &miss); | |
| 2352 } | 2353 } |
| 2353 | 2354 |
| 2354 // Make sure that it's okay not to patch the on stack receiver | 2355 // Make sure that it's okay not to patch the on stack receiver |
| 2355 // unless we're doing a receiver map check. | 2356 // unless we're doing a receiver map check. |
| 2356 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2357 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2357 | 2358 |
| 2358 SharedFunctionInfo* function_info = function->shared(); | 2359 SharedFunctionInfo* function_info = function->shared(); |
| 2359 switch (check) { | 2360 switch (check) { |
| 2360 case RECEIVER_MAP_CHECK: | 2361 case RECEIVER_MAP_CHECK: |
| 2361 __ IncrementCounter(masm()->isolate()->counters()->call_const(), | 2362 __ IncrementCounter(masm()->isolate()->counters()->call_const(), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2374 break; | 2375 break; |
| 2375 | 2376 |
| 2376 case STRING_CHECK: | 2377 case STRING_CHECK: |
| 2377 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2378 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2378 // Calling non-strict non-builtins with a value as the receiver | 2379 // Calling non-strict non-builtins with a value as the receiver |
| 2379 // requires boxing. | 2380 // requires boxing. |
| 2380 __ jmp(&miss); | 2381 __ jmp(&miss); |
| 2381 } else { | 2382 } else { |
| 2382 // Check that the object is a two-byte string or a symbol. | 2383 // Check that the object is a two-byte string or a symbol. |
| 2383 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 2384 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
| 2384 __ b(hs, &miss); | 2385 __ b(ge, &miss); |
| 2385 // Check that the maps starting from the prototype haven't changed. | 2386 // Check that the maps starting from the prototype haven't changed. |
| 2386 GenerateDirectLoadGlobalFunctionPrototype( | 2387 GenerateDirectLoadGlobalFunctionPrototype( |
| 2387 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); | 2388 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); |
| 2388 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2389 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2389 r1, r4, name, &miss); | 2390 r1, r4, name, &miss); |
| 2390 } | 2391 } |
| 2391 break; | 2392 break; |
| 2392 | 2393 |
| 2393 case NUMBER_CHECK: { | 2394 case NUMBER_CHECK: { |
| 2394 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2395 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2395 // Calling non-strict non-builtins with a value as the receiver | 2396 // Calling non-strict non-builtins with a value as the receiver |
| 2396 // requires boxing. | 2397 // requires boxing. |
| 2397 __ jmp(&miss); | 2398 __ jmp(&miss); |
| 2398 } else { | 2399 } else { |
| 2399 Label fast; | 2400 Label fast; |
| 2400 // Check that the object is a smi or a heap number. | 2401 // Check that the object is a smi or a heap number. |
| 2401 __ tst(r1, Operand(kSmiTagMask)); | 2402 __ JumpIfSmi(r1, &fast); |
| 2402 __ b(eq, &fast); | |
| 2403 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2403 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
| 2404 __ b(ne, &miss); | 2404 __ b(ne, &miss); |
| 2405 __ bind(&fast); | 2405 __ bind(&fast); |
| 2406 // Check that the maps starting from the prototype haven't changed. | 2406 // Check that the maps starting from the prototype haven't changed. |
| 2407 GenerateDirectLoadGlobalFunctionPrototype( | 2407 GenerateDirectLoadGlobalFunctionPrototype( |
| 2408 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2408 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); |
| 2409 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2409 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2410 r1, r4, name, &miss); | 2410 r1, r4, name, &miss); |
| 2411 } | 2411 } |
| 2412 break; | 2412 break; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2433 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2433 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2434 r1, r4, name, &miss); | 2434 r1, r4, name, &miss); |
| 2435 } | 2435 } |
| 2436 break; | 2436 break; |
| 2437 } | 2437 } |
| 2438 | 2438 |
| 2439 default: | 2439 default: |
| 2440 UNREACHABLE(); | 2440 UNREACHABLE(); |
| 2441 } | 2441 } |
| 2442 | 2442 |
| 2443 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2443 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2444 ? CALL_AS_FUNCTION |
| 2445 : CALL_AS_METHOD; |
| 2446 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); |
| 2444 | 2447 |
| 2445 // Handle call cache miss. | 2448 // Handle call cache miss. |
| 2446 __ bind(&miss); | 2449 __ bind(&miss); |
| 2447 MaybeObject* maybe_result = GenerateMissBranch(); | 2450 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2448 if (maybe_result->IsFailure()) return maybe_result; | 2451 if (maybe_result->IsFailure()) return maybe_result; |
| 2449 | 2452 |
| 2450 // Return the generated code. | 2453 // Return the generated code. |
| 2451 return GetCode(function); | 2454 return GetCode(function); |
| 2452 } | 2455 } |
| 2453 | 2456 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2466 | 2469 |
| 2467 // Get the number of arguments. | 2470 // Get the number of arguments. |
| 2468 const int argc = arguments().immediate(); | 2471 const int argc = arguments().immediate(); |
| 2469 | 2472 |
| 2470 LookupResult lookup; | 2473 LookupResult lookup; |
| 2471 LookupPostInterceptor(holder, name, &lookup); | 2474 LookupPostInterceptor(holder, name, &lookup); |
| 2472 | 2475 |
| 2473 // Get the receiver from the stack. | 2476 // Get the receiver from the stack. |
| 2474 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2477 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2475 | 2478 |
| 2476 CallInterceptorCompiler compiler(this, arguments(), r2); | 2479 CallInterceptorCompiler compiler(this, arguments(), r2, extra_ic_state_); |
| 2477 MaybeObject* result = compiler.Compile(masm(), | 2480 MaybeObject* result = compiler.Compile(masm(), |
| 2478 object, | 2481 object, |
| 2479 holder, | 2482 holder, |
| 2480 name, | 2483 name, |
| 2481 &lookup, | 2484 &lookup, |
| 2482 r1, | 2485 r1, |
| 2483 r3, | 2486 r3, |
| 2484 r4, | 2487 r4, |
| 2485 r0, | 2488 r0, |
| 2486 &miss); | 2489 &miss); |
| 2487 if (result->IsFailure()) { | 2490 if (result->IsFailure()) { |
| 2488 return result; | 2491 return result; |
| 2489 } | 2492 } |
| 2490 | 2493 |
| 2491 // Move returned value, the function to call, to r1. | 2494 // Move returned value, the function to call, to r1. |
| 2492 __ mov(r1, r0); | 2495 __ mov(r1, r0); |
| 2493 // Restore receiver. | 2496 // Restore receiver. |
| 2494 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2497 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 2495 | 2498 |
| 2496 GenerateCallFunction(masm(), object, arguments(), &miss); | 2499 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); |
| 2497 | 2500 |
| 2498 // Handle call cache miss. | 2501 // Handle call cache miss. |
| 2499 __ bind(&miss); | 2502 __ bind(&miss); |
| 2500 MaybeObject* maybe_result = GenerateMissBranch(); | 2503 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2501 if (maybe_result->IsFailure()) return maybe_result; | 2504 if (maybe_result->IsFailure()) return maybe_result; |
| 2502 | 2505 |
| 2503 // Return the generated code. | 2506 // Return the generated code. |
| 2504 return GetCode(INTERCEPTOR, name); | 2507 return GetCode(INTERCEPTOR, name); |
| 2505 } | 2508 } |
| 2506 | 2509 |
| 2507 | 2510 |
| 2508 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2511 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2509 JSObject* object, | 2512 GlobalObject* holder, |
| 2510 GlobalObject* holder, | 2513 JSGlobalPropertyCell* cell, |
| 2511 JSGlobalPropertyCell* cell, | 2514 JSFunction* function, |
| 2512 JSFunction* function, | 2515 String* name) { |
| 2513 String* name, | |
| 2514 Code::ExtraICState extra_ic_state) { | |
| 2515 // ----------- S t a t e ------------- | 2516 // ----------- S t a t e ------------- |
| 2516 // -- r2 : name | 2517 // -- r2 : name |
| 2517 // -- lr : return address | 2518 // -- lr : return address |
| 2518 // ----------------------------------- | 2519 // ----------------------------------- |
| 2519 | 2520 |
| 2520 if (HasCustomCallGenerator(function)) { | 2521 if (HasCustomCallGenerator(function)) { |
| 2521 MaybeObject* maybe_result = CompileCustomCall( | 2522 MaybeObject* maybe_result = CompileCustomCall( |
| 2522 object, holder, cell, function, name); | 2523 object, holder, cell, function, name); |
| 2523 Object* result; | 2524 Object* result; |
| 2524 if (!maybe_result->ToObject(&result)) return maybe_result; | 2525 if (!maybe_result->ToObject(&result)) return maybe_result; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2546 | 2547 |
| 2547 // Setup the context (function already in r1). | 2548 // Setup the context (function already in r1). |
| 2548 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 2549 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 2549 | 2550 |
| 2550 // Jump to the cached code (tail call). | 2551 // Jump to the cached code (tail call). |
| 2551 Counters* counters = masm()->isolate()->counters(); | 2552 Counters* counters = masm()->isolate()->counters(); |
| 2552 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2553 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
| 2553 ASSERT(function->is_compiled()); | 2554 ASSERT(function->is_compiled()); |
| 2554 Handle<Code> code(function->code()); | 2555 Handle<Code> code(function->code()); |
| 2555 ParameterCount expected(function->shared()->formal_parameter_count()); | 2556 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2556 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 2557 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2557 ? CALL_AS_FUNCTION | 2558 ? CALL_AS_FUNCTION |
| 2558 : CALL_AS_METHOD; | 2559 : CALL_AS_METHOD; |
| 2559 if (V8::UseCrankshaft()) { | 2560 if (V8::UseCrankshaft()) { |
| 2560 // TODO(kasperl): For now, we always call indirectly through the | 2561 // TODO(kasperl): For now, we always call indirectly through the |
| 2561 // code field in the function to allow recompilation to take effect | 2562 // code field in the function to allow recompilation to take effect |
| 2562 // without changing any of the call sites. | 2563 // without changing any of the call sites. |
| 2563 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 2564 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 2564 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, | 2565 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, |
| 2565 NullCallWrapper(), call_kind); | 2566 NullCallWrapper(), call_kind); |
| 2566 } else { | 2567 } else { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2611 String* name) { | 2612 String* name) { |
| 2612 // ----------- S t a t e ------------- | 2613 // ----------- S t a t e ------------- |
| 2613 // -- r0 : value | 2614 // -- r0 : value |
| 2614 // -- r1 : receiver | 2615 // -- r1 : receiver |
| 2615 // -- r2 : name | 2616 // -- r2 : name |
| 2616 // -- lr : return address | 2617 // -- lr : return address |
| 2617 // ----------------------------------- | 2618 // ----------------------------------- |
| 2618 Label miss; | 2619 Label miss; |
| 2619 | 2620 |
| 2620 // Check that the object isn't a smi. | 2621 // Check that the object isn't a smi. |
| 2621 __ tst(r1, Operand(kSmiTagMask)); | 2622 __ JumpIfSmi(r1, &miss); |
| 2622 __ b(eq, &miss); | |
| 2623 | 2623 |
| 2624 // Check that the map of the object hasn't changed. | 2624 // Check that the map of the object hasn't changed. |
| 2625 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2625 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 2626 __ cmp(r3, Operand(Handle<Map>(object->map()))); | 2626 __ cmp(r3, Operand(Handle<Map>(object->map()))); |
| 2627 __ b(ne, &miss); | 2627 __ b(ne, &miss); |
| 2628 | 2628 |
| 2629 // Perform global security token check if needed. | 2629 // Perform global security token check if needed. |
| 2630 if (object->IsJSGlobalProxy()) { | 2630 if (object->IsJSGlobalProxy()) { |
| 2631 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2631 __ CheckAccessGlobalProxy(r1, r3, &miss); |
| 2632 } | 2632 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2659 String* name) { | 2659 String* name) { |
| 2660 // ----------- S t a t e ------------- | 2660 // ----------- S t a t e ------------- |
| 2661 // -- r0 : value | 2661 // -- r0 : value |
| 2662 // -- r1 : receiver | 2662 // -- r1 : receiver |
| 2663 // -- r2 : name | 2663 // -- r2 : name |
| 2664 // -- lr : return address | 2664 // -- lr : return address |
| 2665 // ----------------------------------- | 2665 // ----------------------------------- |
| 2666 Label miss; | 2666 Label miss; |
| 2667 | 2667 |
| 2668 // Check that the object isn't a smi. | 2668 // Check that the object isn't a smi. |
| 2669 __ tst(r1, Operand(kSmiTagMask)); | 2669 __ JumpIfSmi(r1, &miss); |
| 2670 __ b(eq, &miss); | |
| 2671 | 2670 |
| 2672 // Check that the map of the object hasn't changed. | 2671 // Check that the map of the object hasn't changed. |
| 2673 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2672 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 2674 __ cmp(r3, Operand(Handle<Map>(receiver->map()))); | 2673 __ cmp(r3, Operand(Handle<Map>(receiver->map()))); |
| 2675 __ b(ne, &miss); | 2674 __ b(ne, &miss); |
| 2676 | 2675 |
| 2677 // Perform global security token check if needed. | 2676 // Perform global security token check if needed. |
| 2678 if (receiver->IsJSGlobalProxy()) { | 2677 if (receiver->IsJSGlobalProxy()) { |
| 2679 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2678 __ CheckAccessGlobalProxy(r1, r3, &miss); |
| 2680 } | 2679 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2750 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
| 2752 JSObject* object, | 2751 JSObject* object, |
| 2753 JSObject* last) { | 2752 JSObject* last) { |
| 2754 // ----------- S t a t e ------------- | 2753 // ----------- S t a t e ------------- |
| 2755 // -- r0 : receiver | 2754 // -- r0 : receiver |
| 2756 // -- lr : return address | 2755 // -- lr : return address |
| 2757 // ----------------------------------- | 2756 // ----------------------------------- |
| 2758 Label miss; | 2757 Label miss; |
| 2759 | 2758 |
| 2760 // Check that receiver is not a smi. | 2759 // Check that receiver is not a smi. |
| 2761 __ tst(r0, Operand(kSmiTagMask)); | 2760 __ JumpIfSmi(r0, &miss); |
| 2762 __ b(eq, &miss); | |
| 2763 | 2761 |
| 2764 // Check the maps of the full prototype chain. | 2762 // Check the maps of the full prototype chain. |
| 2765 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); | 2763 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); |
| 2766 | 2764 |
| 2767 // If the last object in the prototype chain is a global object, | 2765 // If the last object in the prototype chain is a global object, |
| 2768 // check that the global property cell is empty. | 2766 // check that the global property cell is empty. |
| 2769 if (last->IsGlobalObject()) { | 2767 if (last->IsGlobalObject()) { |
| 2770 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 2768 MaybeObject* cell = GenerateCheckPropertyCell(masm(), |
| 2771 GlobalObject::cast(last), | 2769 GlobalObject::cast(last), |
| 2772 name, | 2770 name, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2896 // -- r0 : receiver | 2894 // -- r0 : receiver |
| 2897 // -- r2 : name | 2895 // -- r2 : name |
| 2898 // -- lr : return address | 2896 // -- lr : return address |
| 2899 // ----------------------------------- | 2897 // ----------------------------------- |
| 2900 Label miss; | 2898 Label miss; |
| 2901 | 2899 |
| 2902 // If the object is the holder then we know that it's a global | 2900 // If the object is the holder then we know that it's a global |
| 2903 // object which can only happen for contextual calls. In this case, | 2901 // object which can only happen for contextual calls. In this case, |
| 2904 // the receiver cannot be a smi. | 2902 // the receiver cannot be a smi. |
| 2905 if (object != holder) { | 2903 if (object != holder) { |
| 2906 __ tst(r0, Operand(kSmiTagMask)); | 2904 __ JumpIfSmi(r0, &miss); |
| 2907 __ b(eq, &miss); | |
| 2908 } | 2905 } |
| 2909 | 2906 |
| 2910 // Check that the map of the global has not changed. | 2907 // Check that the map of the global has not changed. |
| 2911 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); | 2908 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); |
| 2912 | 2909 |
| 2913 // Get the value from the cell. | 2910 // Get the value from the cell. |
| 2914 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 2911 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
| 2915 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 2912 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
| 2916 | 2913 |
| 2917 // Check for deleted property if property can actually be deleted. | 2914 // Check for deleted property if property can actually be deleted. |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3107 | 3104 |
| 3108 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); | 3105 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); |
| 3109 __ bind(&miss); | 3106 __ bind(&miss); |
| 3110 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); | 3107 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); |
| 3111 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3108 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3112 | 3109 |
| 3113 return GetCode(CALLBACKS, name); | 3110 return GetCode(CALLBACKS, name); |
| 3114 } | 3111 } |
| 3115 | 3112 |
| 3116 | 3113 |
| 3117 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { | 3114 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { |
| 3118 // ----------- S t a t e ------------- | 3115 // ----------- S t a t e ------------- |
| 3119 // -- lr : return address | 3116 // -- lr : return address |
| 3120 // -- r0 : key | 3117 // -- r0 : key |
| 3121 // -- r1 : receiver | 3118 // -- r1 : receiver |
| 3122 // ----------------------------------- | 3119 // ----------------------------------- |
| 3123 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode(); | |
| 3124 Code* stub; | 3120 Code* stub; |
| 3121 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3122 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); |
| 3125 if (!maybe_stub->To(&stub)) return maybe_stub; | 3123 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3126 __ DispatchMap(r1, | 3124 __ DispatchMap(r1, |
| 3127 r2, | 3125 r2, |
| 3128 Handle<Map>(receiver_map), | 3126 Handle<Map>(receiver_map), |
| 3129 Handle<Code>(stub), | 3127 Handle<Code>(stub), |
| 3130 DO_SMI_CHECK); | 3128 DO_SMI_CHECK); |
| 3131 | 3129 |
| 3132 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3130 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3133 __ Jump(ic, RelocInfo::CODE_TARGET); | 3131 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3134 | 3132 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3198 | 3196 |
| 3199 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); | 3197 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); |
| 3200 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | 3198 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3201 __ Jump(ic, RelocInfo::CODE_TARGET); | 3199 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3202 | 3200 |
| 3203 // Return the generated code. | 3201 // Return the generated code. |
| 3204 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 3202 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 3205 } | 3203 } |
| 3206 | 3204 |
| 3207 | 3205 |
| 3208 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( | 3206 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { |
| 3209 Map* receiver_map) { | |
| 3210 // ----------- S t a t e ------------- | 3207 // ----------- S t a t e ------------- |
| 3211 // -- r0 : value | 3208 // -- r0 : value |
| 3212 // -- r1 : key | 3209 // -- r1 : key |
| 3213 // -- r2 : receiver | 3210 // -- r2 : receiver |
| 3214 // -- lr : return address | 3211 // -- lr : return address |
| 3215 // -- r3 : scratch | 3212 // -- r3 : scratch |
| 3216 // ----------------------------------- | 3213 // ----------------------------------- |
| 3214 Code* stub; |
| 3215 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3217 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 3216 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 3218 MaybeObject* maybe_stub = | 3217 MaybeObject* maybe_stub = |
| 3219 KeyedStoreFastElementStub(is_js_array).TryGetCode(); | 3218 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); |
| 3220 Code* stub; | |
| 3221 if (!maybe_stub->To(&stub)) return maybe_stub; | 3219 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3222 __ DispatchMap(r2, | 3220 __ DispatchMap(r2, |
| 3223 r3, | 3221 r3, |
| 3224 Handle<Map>(receiver_map), | 3222 Handle<Map>(receiver_map), |
| 3225 Handle<Code>(stub), | 3223 Handle<Code>(stub), |
| 3226 DO_SMI_CHECK); | 3224 DO_SMI_CHECK); |
| 3227 | 3225 |
| 3228 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3226 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3229 __ Jump(ic, RelocInfo::CODE_TARGET); | 3227 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3230 | 3228 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3284 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 3282 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 3285 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); | 3283 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); |
| 3286 __ cmp(r2, r7); | 3284 __ cmp(r2, r7); |
| 3287 __ b(ne, &generic_stub_call); | 3285 __ b(ne, &generic_stub_call); |
| 3288 #endif | 3286 #endif |
| 3289 | 3287 |
| 3290 // Load the initial map and verify that it is in fact a map. | 3288 // Load the initial map and verify that it is in fact a map. |
| 3291 // r1: constructor function | 3289 // r1: constructor function |
| 3292 // r7: undefined | 3290 // r7: undefined |
| 3293 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 3291 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3294 __ tst(r2, Operand(kSmiTagMask)); | 3292 __ JumpIfSmi(r2, &generic_stub_call); |
| 3295 __ b(eq, &generic_stub_call); | |
| 3296 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 3293 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
| 3297 __ b(ne, &generic_stub_call); | 3294 __ b(ne, &generic_stub_call); |
| 3298 | 3295 |
| 3299 #ifdef DEBUG | 3296 #ifdef DEBUG |
| 3300 // Cannot construct functions this way. | 3297 // Cannot construct functions this way. |
| 3301 // r0: argc | 3298 // r0: argc |
| 3302 // r1: constructor function | 3299 // r1: constructor function |
| 3303 // r2: initial map | 3300 // r2: initial map |
| 3304 // r7: undefined | 3301 // r7: undefined |
| 3305 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); | 3302 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3402 // construction. | 3399 // construction. |
| 3403 __ bind(&generic_stub_call); | 3400 __ bind(&generic_stub_call); |
| 3404 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); | 3401 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); |
| 3405 __ Jump(code, RelocInfo::CODE_TARGET); | 3402 __ Jump(code, RelocInfo::CODE_TARGET); |
| 3406 | 3403 |
| 3407 // Return the generated code. | 3404 // Return the generated code. |
| 3408 return GetCode(); | 3405 return GetCode(); |
| 3409 } | 3406 } |
| 3410 | 3407 |
| 3411 | 3408 |
| 3412 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad( | |
| 3413 JSObject*receiver, ExternalArrayType array_type) { | |
| 3414 // ----------- S t a t e ------------- | |
| 3415 // -- lr : return address | |
| 3416 // -- r0 : key | |
| 3417 // -- r1 : receiver | |
| 3418 // ----------------------------------- | |
| 3419 MaybeObject* maybe_stub = | |
| 3420 KeyedLoadExternalArrayStub(array_type).TryGetCode(); | |
| 3421 Code* stub; | |
| 3422 if (!maybe_stub->To(&stub)) return maybe_stub; | |
| 3423 __ DispatchMap(r1, | |
| 3424 r2, | |
| 3425 Handle<Map>(receiver->map()), | |
| 3426 Handle<Code>(stub), | |
| 3427 DO_SMI_CHECK); | |
| 3428 | |
| 3429 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | |
| 3430 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 3431 | |
| 3432 // Return the generated code. | |
| 3433 return GetCode(); | |
| 3434 } | |
| 3435 | |
| 3436 | |
| 3437 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore( | |
| 3438 JSObject* receiver, ExternalArrayType array_type) { | |
| 3439 // ----------- S t a t e ------------- | |
| 3440 // -- r0 : value | |
| 3441 // -- r1 : name | |
| 3442 // -- r2 : receiver | |
| 3443 // -- lr : return address | |
| 3444 // ----------------------------------- | |
| 3445 MaybeObject* maybe_stub = | |
| 3446 KeyedStoreExternalArrayStub(array_type).TryGetCode(); | |
| 3447 Code* stub; | |
| 3448 if (!maybe_stub->To(&stub)) return maybe_stub; | |
| 3449 __ DispatchMap(r2, | |
| 3450 r3, | |
| 3451 Handle<Map>(receiver->map()), | |
| 3452 Handle<Code>(stub), | |
| 3453 DO_SMI_CHECK); | |
| 3454 | |
| 3455 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | |
| 3456 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 3457 | |
| 3458 return GetCode(); | |
| 3459 } | |
| 3460 | |
| 3461 | |
| 3462 #undef __ | 3409 #undef __ |
| 3463 #define __ ACCESS_MASM(masm) | 3410 #define __ ACCESS_MASM(masm) |
| 3464 | 3411 |
| 3465 | 3412 |
| 3466 static bool IsElementTypeSigned(ExternalArrayType array_type) { | 3413 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
| 3467 switch (array_type) { | 3414 MacroAssembler* masm) { |
| 3468 case kExternalByteArray: | 3415 // ---------- S t a t e -------------- |
| 3469 case kExternalShortArray: | 3416 // -- lr : return address |
| 3470 case kExternalIntArray: | 3417 // -- r0 : key |
| 3418 // -- r1 : receiver |
| 3419 // ----------------------------------- |
| 3420 Label slow, miss_force_generic; |
| 3421 |
| 3422 Register key = r0; |
| 3423 Register receiver = r1; |
| 3424 |
| 3425 __ JumpIfNotSmi(key, &miss_force_generic); |
| 3426 __ mov(r2, Operand(key, ASR, kSmiTagSize)); |
| 3427 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 3428 __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5); |
| 3429 __ Ret(); |
| 3430 |
| 3431 __ bind(&slow); |
| 3432 __ IncrementCounter( |
| 3433 masm->isolate()->counters()->keyed_load_external_array_slow(), |
| 3434 1, r2, r3); |
| 3435 |
| 3436 // ---------- S t a t e -------------- |
| 3437 // -- lr : return address |
| 3438 // -- r0 : key |
| 3439 // -- r1 : receiver |
| 3440 // ----------------------------------- |
| 3441 Handle<Code> slow_ic = |
| 3442 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3443 __ Jump(slow_ic, RelocInfo::CODE_TARGET); |
| 3444 |
| 3445 // Miss case, call the runtime. |
| 3446 __ bind(&miss_force_generic); |
| 3447 |
| 3448 // ---------- S t a t e -------------- |
| 3449 // -- lr : return address |
| 3450 // -- r0 : key |
| 3451 // -- r1 : receiver |
| 3452 // ----------------------------------- |
| 3453 |
| 3454 Handle<Code> miss_ic = |
| 3455 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3456 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3457 } |
| 3458 |
| 3459 |
| 3460 static bool IsElementTypeSigned(JSObject::ElementsKind elements_kind) { |
| 3461 switch (elements_kind) { |
| 3462 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3463 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3464 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3471 return true; | 3465 return true; |
| 3472 | 3466 |
| 3473 case kExternalUnsignedByteArray: | 3467 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3474 case kExternalUnsignedShortArray: | 3468 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3475 case kExternalUnsignedIntArray: | 3469 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3470 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3476 return false; | 3471 return false; |
| 3477 | 3472 |
| 3478 default: | 3473 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3474 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3475 case JSObject::FAST_ELEMENTS: |
| 3476 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3477 case JSObject::DICTIONARY_ELEMENTS: |
| 3478 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3479 UNREACHABLE(); | 3479 UNREACHABLE(); |
| 3480 return false; | 3480 return false; |
| 3481 } | 3481 } |
| 3482 return false; |
| 3482 } | 3483 } |
| 3483 | 3484 |
| 3484 | 3485 |
| 3485 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | 3486 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
| 3486 MacroAssembler* masm, | 3487 MacroAssembler* masm, |
| 3487 ExternalArrayType array_type) { | 3488 JSObject::ElementsKind elements_kind) { |
| 3488 // ---------- S t a t e -------------- | 3489 // ---------- S t a t e -------------- |
| 3489 // -- lr : return address | 3490 // -- lr : return address |
| 3490 // -- r0 : key | 3491 // -- r0 : key |
| 3491 // -- r1 : receiver | 3492 // -- r1 : receiver |
| 3492 // ----------------------------------- | 3493 // ----------------------------------- |
| 3493 Label miss_force_generic, slow, failed_allocation; | 3494 Label miss_force_generic, slow, failed_allocation; |
| 3494 | 3495 |
| 3495 Register key = r0; | 3496 Register key = r0; |
| 3496 Register receiver = r1; | 3497 Register receiver = r1; |
| 3497 | 3498 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3511 __ b(lo, &miss_force_generic); | 3512 __ b(lo, &miss_force_generic); |
| 3512 | 3513 |
| 3513 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); | 3514 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| 3514 // r3: base pointer of external storage | 3515 // r3: base pointer of external storage |
| 3515 | 3516 |
| 3516 // We are not untagging smi key and instead work with it | 3517 // We are not untagging smi key and instead work with it |
| 3517 // as if it was premultiplied by 2. | 3518 // as if it was premultiplied by 2. |
| 3518 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); | 3519 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); |
| 3519 | 3520 |
| 3520 Register value = r2; | 3521 Register value = r2; |
| 3521 switch (array_type) { | 3522 switch (elements_kind) { |
| 3522 case kExternalByteArray: | 3523 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3523 __ ldrsb(value, MemOperand(r3, key, LSR, 1)); | 3524 __ ldrsb(value, MemOperand(r3, key, LSR, 1)); |
| 3524 break; | 3525 break; |
| 3525 case kExternalPixelArray: | 3526 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3526 case kExternalUnsignedByteArray: | 3527 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3527 __ ldrb(value, MemOperand(r3, key, LSR, 1)); | 3528 __ ldrb(value, MemOperand(r3, key, LSR, 1)); |
| 3528 break; | 3529 break; |
| 3529 case kExternalShortArray: | 3530 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3530 __ ldrsh(value, MemOperand(r3, key, LSL, 0)); | 3531 __ ldrsh(value, MemOperand(r3, key, LSL, 0)); |
| 3531 break; | 3532 break; |
| 3532 case kExternalUnsignedShortArray: | 3533 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3533 __ ldrh(value, MemOperand(r3, key, LSL, 0)); | 3534 __ ldrh(value, MemOperand(r3, key, LSL, 0)); |
| 3534 break; | 3535 break; |
| 3535 case kExternalIntArray: | 3536 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3536 case kExternalUnsignedIntArray: | 3537 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3537 __ ldr(value, MemOperand(r3, key, LSL, 1)); | 3538 __ ldr(value, MemOperand(r3, key, LSL, 1)); |
| 3538 break; | 3539 break; |
| 3539 case kExternalFloatArray: | 3540 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3540 if (CpuFeatures::IsSupported(VFP3)) { | 3541 if (CpuFeatures::IsSupported(VFP3)) { |
| 3541 CpuFeatures::Scope scope(VFP3); | 3542 CpuFeatures::Scope scope(VFP3); |
| 3542 __ add(r2, r3, Operand(key, LSL, 1)); | 3543 __ add(r2, r3, Operand(key, LSL, 1)); |
| 3543 __ vldr(s0, r2, 0); | 3544 __ vldr(s0, r2, 0); |
| 3544 } else { | 3545 } else { |
| 3545 __ ldr(value, MemOperand(r3, key, LSL, 1)); | 3546 __ ldr(value, MemOperand(r3, key, LSL, 1)); |
| 3546 } | 3547 } |
| 3547 break; | 3548 break; |
| 3548 case kExternalDoubleArray: | 3549 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3549 if (CpuFeatures::IsSupported(VFP3)) { | 3550 if (CpuFeatures::IsSupported(VFP3)) { |
| 3550 CpuFeatures::Scope scope(VFP3); | 3551 CpuFeatures::Scope scope(VFP3); |
| 3551 __ add(r2, r3, Operand(key, LSL, 2)); | 3552 __ add(r2, r3, Operand(key, LSL, 2)); |
| 3552 __ vldr(d0, r2, 0); | 3553 __ vldr(d0, r2, 0); |
| 3553 } else { | 3554 } else { |
| 3554 __ add(r4, r3, Operand(key, LSL, 2)); | 3555 __ add(r4, r3, Operand(key, LSL, 2)); |
| 3555 // r4: pointer to the beginning of the double we want to load. | 3556 // r4: pointer to the beginning of the double we want to load. |
| 3556 __ ldr(r2, MemOperand(r4, 0)); | 3557 __ ldr(r2, MemOperand(r4, 0)); |
| 3557 __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); | 3558 __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); |
| 3558 } | 3559 } |
| 3559 break; | 3560 break; |
| 3560 default: | 3561 case JSObject::FAST_ELEMENTS: |
| 3562 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3563 case JSObject::DICTIONARY_ELEMENTS: |
| 3564 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3561 UNREACHABLE(); | 3565 UNREACHABLE(); |
| 3562 break; | 3566 break; |
| 3563 } | 3567 } |
| 3564 | 3568 |
| 3565 // For integer array types: | 3569 // For integer array types: |
| 3566 // r2: value | 3570 // r2: value |
| 3567 // For float array type: | 3571 // For float array type: |
| 3568 // s0: value (if VFP3 is supported) | 3572 // s0: value (if VFP3 is supported) |
| 3569 // r2: value (if VFP3 is not supported) | 3573 // r2: value (if VFP3 is not supported) |
| 3570 // For double array type: | 3574 // For double array type: |
| 3571 // d0: value (if VFP3 is supported) | 3575 // d0: value (if VFP3 is supported) |
| 3572 // r2/r3: value (if VFP3 is not supported) | 3576 // r2/r3: value (if VFP3 is not supported) |
| 3573 | 3577 |
| 3574 if (array_type == kExternalIntArray) { | 3578 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) { |
| 3575 // For the Int and UnsignedInt array types, we need to see whether | 3579 // For the Int and UnsignedInt array types, we need to see whether |
| 3576 // the value can be represented in a Smi. If not, we need to convert | 3580 // the value can be represented in a Smi. If not, we need to convert |
| 3577 // it to a HeapNumber. | 3581 // it to a HeapNumber. |
| 3578 Label box_int; | 3582 Label box_int; |
| 3579 __ cmp(value, Operand(0xC0000000)); | 3583 __ cmp(value, Operand(0xC0000000)); |
| 3580 __ b(mi, &box_int); | 3584 __ b(mi, &box_int); |
| 3581 // Tag integer as smi and return it. | 3585 // Tag integer as smi and return it. |
| 3582 __ mov(r0, Operand(value, LSL, kSmiTagSize)); | 3586 __ mov(r0, Operand(value, LSL, kSmiTagSize)); |
| 3583 __ Ret(); | 3587 __ Ret(); |
| 3584 | 3588 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3608 dest, | 3612 dest, |
| 3609 d0, | 3613 d0, |
| 3610 dst1, | 3614 dst1, |
| 3611 dst2, | 3615 dst2, |
| 3612 r9, | 3616 r9, |
| 3613 s0); | 3617 s0); |
| 3614 __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 3618 __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 3615 __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 3619 __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 3616 __ Ret(); | 3620 __ Ret(); |
| 3617 } | 3621 } |
| 3618 } else if (array_type == kExternalUnsignedIntArray) { | 3622 } else if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 3619 // The test is different for unsigned int values. Since we need | 3623 // The test is different for unsigned int values. Since we need |
| 3620 // the value to be in the range of a positive smi, we can't | 3624 // the value to be in the range of a positive smi, we can't |
| 3621 // handle either of the top two bits being set in the value. | 3625 // handle either of the top two bits being set in the value. |
| 3622 if (CpuFeatures::IsSupported(VFP3)) { | 3626 if (CpuFeatures::IsSupported(VFP3)) { |
| 3623 CpuFeatures::Scope scope(VFP3); | 3627 CpuFeatures::Scope scope(VFP3); |
| 3624 Label box_int, done; | 3628 Label box_int, done; |
| 3625 __ tst(value, Operand(0xC0000000)); | 3629 __ tst(value, Operand(0xC0000000)); |
| 3626 __ b(ne, &box_int); | 3630 __ b(ne, &box_int); |
| 3627 // Tag integer as smi and return it. | 3631 // Tag integer as smi and return it. |
| 3628 __ mov(r0, Operand(value, LSL, kSmiTagSize)); | 3632 __ mov(r0, Operand(value, LSL, kSmiTagSize)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3673 // space. | 3677 // space. |
| 3674 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 3678 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 3675 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); | 3679 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); |
| 3676 | 3680 |
| 3677 __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset)); | 3681 __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset)); |
| 3678 __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); | 3682 __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); |
| 3679 | 3683 |
| 3680 __ mov(r0, r4); | 3684 __ mov(r0, r4); |
| 3681 __ Ret(); | 3685 __ Ret(); |
| 3682 } | 3686 } |
| 3683 } else if (array_type == kExternalFloatArray) { | 3687 } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3684 // For the floating-point array type, we need to always allocate a | 3688 // For the floating-point array type, we need to always allocate a |
| 3685 // HeapNumber. | 3689 // HeapNumber. |
| 3686 if (CpuFeatures::IsSupported(VFP3)) { | 3690 if (CpuFeatures::IsSupported(VFP3)) { |
| 3687 CpuFeatures::Scope scope(VFP3); | 3691 CpuFeatures::Scope scope(VFP3); |
| 3688 // Allocate a HeapNumber for the result. Don't use r0 and r1 as | 3692 // Allocate a HeapNumber for the result. Don't use r0 and r1 as |
| 3689 // AllocateHeapNumber clobbers all registers - also when jumping due to | 3693 // AllocateHeapNumber clobbers all registers - also when jumping due to |
| 3690 // exhausted young space. | 3694 // exhausted young space. |
| 3691 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 3695 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 3692 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); | 3696 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); |
| 3693 __ vcvt_f64_f32(d0, s0); | 3697 __ vcvt_f64_f32(d0, s0); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3743 | 3747 |
| 3744 __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord)); | 3748 __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord)); |
| 3745 __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord)); | 3749 __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord)); |
| 3746 | 3750 |
| 3747 __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset)); | 3751 __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset)); |
| 3748 __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); | 3752 __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); |
| 3749 | 3753 |
| 3750 __ mov(r0, r3); | 3754 __ mov(r0, r3); |
| 3751 __ Ret(); | 3755 __ Ret(); |
| 3752 } | 3756 } |
| 3753 } else if (array_type == kExternalDoubleArray) { | 3757 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3754 if (CpuFeatures::IsSupported(VFP3)) { | 3758 if (CpuFeatures::IsSupported(VFP3)) { |
| 3755 CpuFeatures::Scope scope(VFP3); | 3759 CpuFeatures::Scope scope(VFP3); |
| 3756 // Allocate a HeapNumber for the result. Don't use r0 and r1 as | 3760 // Allocate a HeapNumber for the result. Don't use r0 and r1 as |
| 3757 // AllocateHeapNumber clobbers all registers - also when jumping due to | 3761 // AllocateHeapNumber clobbers all registers - also when jumping due to |
| 3758 // exhausted young space. | 3762 // exhausted young space. |
| 3759 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 3763 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 3760 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); | 3764 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); |
| 3761 __ sub(r1, r2, Operand(kHeapObjectTag)); | 3765 __ sub(r1, r2, Operand(kHeapObjectTag)); |
| 3762 __ vstr(d0, r1, HeapNumber::kValueOffset); | 3766 __ vstr(d0, r1, HeapNumber::kValueOffset); |
| 3763 | 3767 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3800 | 3804 |
| 3801 __ bind(&miss_force_generic); | 3805 __ bind(&miss_force_generic); |
| 3802 Code* stub = masm->isolate()->builtins()->builtin( | 3806 Code* stub = masm->isolate()->builtins()->builtin( |
| 3803 Builtins::kKeyedLoadIC_MissForceGeneric); | 3807 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3804 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 3808 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); |
| 3805 } | 3809 } |
| 3806 | 3810 |
| 3807 | 3811 |
| 3808 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3812 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
| 3809 MacroAssembler* masm, | 3813 MacroAssembler* masm, |
| 3810 ExternalArrayType array_type) { | 3814 JSObject::ElementsKind elements_kind) { |
| 3811 // ---------- S t a t e -------------- | 3815 // ---------- S t a t e -------------- |
| 3812 // -- r0 : value | 3816 // -- r0 : value |
| 3813 // -- r1 : key | 3817 // -- r1 : key |
| 3814 // -- r2 : receiver | 3818 // -- r2 : receiver |
| 3815 // -- lr : return address | 3819 // -- lr : return address |
| 3816 // ----------------------------------- | 3820 // ----------------------------------- |
| 3817 Label slow, check_heap_number, miss_force_generic; | 3821 Label slow, check_heap_number, miss_force_generic; |
| 3818 | 3822 |
| 3819 // Register usage. | 3823 // Register usage. |
| 3820 Register value = r0; | 3824 Register value = r0; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3834 __ SmiUntag(r4, key); | 3838 __ SmiUntag(r4, key); |
| 3835 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); | 3839 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); |
| 3836 __ cmp(r4, ip); | 3840 __ cmp(r4, ip); |
| 3837 // Unsigned comparison catches both negative and too-large values. | 3841 // Unsigned comparison catches both negative and too-large values. |
| 3838 __ b(hs, &miss_force_generic); | 3842 __ b(hs, &miss_force_generic); |
| 3839 | 3843 |
| 3840 // Handle both smis and HeapNumbers in the fast path. Go to the | 3844 // Handle both smis and HeapNumbers in the fast path. Go to the |
| 3841 // runtime for all other kinds of values. | 3845 // runtime for all other kinds of values. |
| 3842 // r3: external array. | 3846 // r3: external array. |
| 3843 // r4: key (integer). | 3847 // r4: key (integer). |
| 3844 if (array_type == kExternalPixelArray) { | 3848 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
| 3845 // Double to pixel conversion is only implemented in the runtime for now. | 3849 // Double to pixel conversion is only implemented in the runtime for now. |
| 3846 __ JumpIfNotSmi(value, &slow); | 3850 __ JumpIfNotSmi(value, &slow); |
| 3847 } else { | 3851 } else { |
| 3848 __ JumpIfNotSmi(value, &check_heap_number); | 3852 __ JumpIfNotSmi(value, &check_heap_number); |
| 3849 } | 3853 } |
| 3850 __ SmiUntag(r5, value); | 3854 __ SmiUntag(r5, value); |
| 3851 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); | 3855 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| 3852 | 3856 |
| 3853 // r3: base pointer of external storage. | 3857 // r3: base pointer of external storage. |
| 3854 // r4: key (integer). | 3858 // r4: key (integer). |
| 3855 // r5: value (integer). | 3859 // r5: value (integer). |
| 3856 switch (array_type) { | 3860 switch (elements_kind) { |
| 3857 case kExternalPixelArray: | 3861 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3858 // Clamp the value to [0..255]. | 3862 // Clamp the value to [0..255]. |
| 3859 __ Usat(r5, 8, Operand(r5)); | 3863 __ Usat(r5, 8, Operand(r5)); |
| 3860 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 3864 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3861 break; | 3865 break; |
| 3862 case kExternalByteArray: | 3866 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3863 case kExternalUnsignedByteArray: | 3867 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3864 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 3868 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3865 break; | 3869 break; |
| 3866 case kExternalShortArray: | 3870 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3867 case kExternalUnsignedShortArray: | 3871 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3868 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | 3872 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| 3869 break; | 3873 break; |
| 3870 case kExternalIntArray: | 3874 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3871 case kExternalUnsignedIntArray: | 3875 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3872 __ str(r5, MemOperand(r3, r4, LSL, 2)); | 3876 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| 3873 break; | 3877 break; |
| 3874 case kExternalFloatArray: | 3878 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3875 // Perform int-to-float conversion and store to memory. | 3879 // Perform int-to-float conversion and store to memory. |
| 3876 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9); | 3880 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9); |
| 3877 break; | 3881 break; |
| 3878 case kExternalDoubleArray: | 3882 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3879 __ add(r3, r3, Operand(r4, LSL, 3)); | 3883 __ add(r3, r3, Operand(r4, LSL, 3)); |
| 3880 // r3: effective address of the double element | 3884 // r3: effective address of the double element |
| 3881 FloatingPointHelper::Destination destination; | 3885 FloatingPointHelper::Destination destination; |
| 3882 if (CpuFeatures::IsSupported(VFP3)) { | 3886 if (CpuFeatures::IsSupported(VFP3)) { |
| 3883 destination = FloatingPointHelper::kVFPRegisters; | 3887 destination = FloatingPointHelper::kVFPRegisters; |
| 3884 } else { | 3888 } else { |
| 3885 destination = FloatingPointHelper::kCoreRegisters; | 3889 destination = FloatingPointHelper::kCoreRegisters; |
| 3886 } | 3890 } |
| 3887 FloatingPointHelper::ConvertIntToDouble( | 3891 FloatingPointHelper::ConvertIntToDouble( |
| 3888 masm, r5, destination, | 3892 masm, r5, destination, |
| 3889 d0, r6, r7, // These are: double_dst, dst1, dst2. | 3893 d0, r6, r7, // These are: double_dst, dst1, dst2. |
| 3890 r4, s2); // These are: scratch2, single_scratch. | 3894 r4, s2); // These are: scratch2, single_scratch. |
| 3891 if (destination == FloatingPointHelper::kVFPRegisters) { | 3895 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 3892 CpuFeatures::Scope scope(VFP3); | 3896 CpuFeatures::Scope scope(VFP3); |
| 3893 __ vstr(d0, r3, 0); | 3897 __ vstr(d0, r3, 0); |
| 3894 } else { | 3898 } else { |
| 3895 __ str(r6, MemOperand(r3, 0)); | 3899 __ str(r6, MemOperand(r3, 0)); |
| 3896 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); | 3900 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); |
| 3897 } | 3901 } |
| 3898 break; | 3902 break; |
| 3899 default: | 3903 case JSObject::FAST_ELEMENTS: |
| 3904 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3905 case JSObject::DICTIONARY_ELEMENTS: |
| 3906 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3900 UNREACHABLE(); | 3907 UNREACHABLE(); |
| 3901 break; | 3908 break; |
| 3902 } | 3909 } |
| 3903 | 3910 |
| 3904 // Entry registers are intact, r0 holds the value which is the return value. | 3911 // Entry registers are intact, r0 holds the value which is the return value. |
| 3905 __ Ret(); | 3912 __ Ret(); |
| 3906 | 3913 |
| 3907 if (array_type != kExternalPixelArray) { | 3914 if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
| 3908 // r3: external array. | 3915 // r3: external array. |
| 3909 // r4: index (integer). | 3916 // r4: index (integer). |
| 3910 __ bind(&check_heap_number); | 3917 __ bind(&check_heap_number); |
| 3911 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); | 3918 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); |
| 3912 __ b(ne, &slow); | 3919 __ b(ne, &slow); |
| 3913 | 3920 |
| 3914 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); | 3921 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| 3915 | 3922 |
| 3916 // r3: base pointer of external storage. | 3923 // r3: base pointer of external storage. |
| 3917 // r4: key (integer). | 3924 // r4: key (integer). |
| 3918 | 3925 |
| 3919 // The WebGL specification leaves the behavior of storing NaN and | 3926 // The WebGL specification leaves the behavior of storing NaN and |
| 3920 // +/-Infinity into integer arrays basically undefined. For more | 3927 // +/-Infinity into integer arrays basically undefined. For more |
| 3921 // reproducible behavior, convert these to zero. | 3928 // reproducible behavior, convert these to zero. |
| 3922 if (CpuFeatures::IsSupported(VFP3)) { | 3929 if (CpuFeatures::IsSupported(VFP3)) { |
| 3923 CpuFeatures::Scope scope(VFP3); | 3930 CpuFeatures::Scope scope(VFP3); |
| 3924 | 3931 |
| 3925 if (array_type == kExternalFloatArray) { | 3932 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3926 // vldr requires offset to be a multiple of 4 so we can not | 3933 // vldr requires offset to be a multiple of 4 so we can not |
| 3927 // include -kHeapObjectTag into it. | 3934 // include -kHeapObjectTag into it. |
| 3928 __ sub(r5, r0, Operand(kHeapObjectTag)); | 3935 __ sub(r5, r0, Operand(kHeapObjectTag)); |
| 3929 __ vldr(d0, r5, HeapNumber::kValueOffset); | 3936 __ vldr(d0, r5, HeapNumber::kValueOffset); |
| 3930 __ add(r5, r3, Operand(r4, LSL, 2)); | 3937 __ add(r5, r3, Operand(r4, LSL, 2)); |
| 3931 __ vcvt_f32_f64(s0, d0); | 3938 __ vcvt_f32_f64(s0, d0); |
| 3932 __ vstr(s0, r5, 0); | 3939 __ vstr(s0, r5, 0); |
| 3933 } else if (array_type == kExternalDoubleArray) { | 3940 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3934 __ sub(r5, r0, Operand(kHeapObjectTag)); | 3941 __ sub(r5, r0, Operand(kHeapObjectTag)); |
| 3935 __ vldr(d0, r5, HeapNumber::kValueOffset); | 3942 __ vldr(d0, r5, HeapNumber::kValueOffset); |
| 3936 __ add(r5, r3, Operand(r4, LSL, 3)); | 3943 __ add(r5, r3, Operand(r4, LSL, 3)); |
| 3937 __ vstr(d0, r5, 0); | 3944 __ vstr(d0, r5, 0); |
| 3938 } else { | 3945 } else { |
| 3939 // Need to perform float-to-int conversion. | |
| 3940 // Test for NaN or infinity (both give zero). | |
| 3941 __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset)); | |
| 3942 | |
| 3943 // Hoisted load. vldr requires offset to be a multiple of 4 so we can | 3946 // Hoisted load. vldr requires offset to be a multiple of 4 so we can |
| 3944 // not include -kHeapObjectTag into it. | 3947 // not include -kHeapObjectTag into it. |
| 3945 __ sub(r5, value, Operand(kHeapObjectTag)); | 3948 __ sub(r5, value, Operand(kHeapObjectTag)); |
| 3946 __ vldr(d0, r5, HeapNumber::kValueOffset); | 3949 __ vldr(d0, r5, HeapNumber::kValueOffset); |
| 3950 __ EmitECMATruncate(r5, d0, s2, r6, r7, r9); |
| 3947 | 3951 |
| 3948 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); | 3952 switch (elements_kind) { |
| 3949 // NaNs and Infinities have all-one exponents so they sign extend to -1. | 3953 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3950 __ cmp(r6, Operand(-1)); | 3954 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3951 __ mov(r5, Operand(0), LeaveCC, eq); | |
| 3952 | |
| 3953 // Not infinity or NaN simply convert to int. | |
| 3954 if (IsElementTypeSigned(array_type)) { | |
| 3955 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne); | |
| 3956 } else { | |
| 3957 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); | |
| 3958 } | |
| 3959 __ vmov(r5, s0, ne); | |
| 3960 | |
| 3961 switch (array_type) { | |
| 3962 case kExternalByteArray: | |
| 3963 case kExternalUnsignedByteArray: | |
| 3964 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 3955 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3965 break; | 3956 break; |
| 3966 case kExternalShortArray: | 3957 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3967 case kExternalUnsignedShortArray: | 3958 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3968 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | 3959 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| 3969 break; | 3960 break; |
| 3970 case kExternalIntArray: | 3961 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3971 case kExternalUnsignedIntArray: | 3962 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3972 __ str(r5, MemOperand(r3, r4, LSL, 2)); | 3963 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| 3973 break; | 3964 break; |
| 3974 default: | 3965 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3966 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3967 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3968 case JSObject::FAST_ELEMENTS: |
| 3969 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3970 case JSObject::DICTIONARY_ELEMENTS: |
| 3971 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3975 UNREACHABLE(); | 3972 UNREACHABLE(); |
| 3976 break; | 3973 break; |
| 3977 } | 3974 } |
| 3978 } | 3975 } |
| 3979 | 3976 |
| 3980 // Entry registers are intact, r0 holds the value which is the return | 3977 // Entry registers are intact, r0 holds the value which is the return |
| 3981 // value. | 3978 // value. |
| 3982 __ Ret(); | 3979 __ Ret(); |
| 3983 } else { | 3980 } else { |
| 3984 // VFP3 is not available do manual conversions. | 3981 // VFP3 is not available do manual conversions. |
| 3985 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); | 3982 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| 3986 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); | 3983 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
| 3987 | 3984 |
| 3988 if (array_type == kExternalFloatArray) { | 3985 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3989 Label done, nan_or_infinity_or_zero; | 3986 Label done, nan_or_infinity_or_zero; |
| 3990 static const int kMantissaInHiWordShift = | 3987 static const int kMantissaInHiWordShift = |
| 3991 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | 3988 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; |
| 3992 | 3989 |
| 3993 static const int kMantissaInLoWordShift = | 3990 static const int kMantissaInLoWordShift = |
| 3994 kBitsPerInt - kMantissaInHiWordShift; | 3991 kBitsPerInt - kMantissaInHiWordShift; |
| 3995 | 3992 |
| 3996 // Test for all special exponent values: zeros, subnormal numbers, NaNs | 3993 // Test for all special exponent values: zeros, subnormal numbers, NaNs |
| 3997 // and infinities. All these should be converted to 0. | 3994 // and infinities. All these should be converted to 0. |
| 3998 __ mov(r7, Operand(HeapNumber::kExponentMask)); | 3995 __ mov(r7, Operand(HeapNumber::kExponentMask)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4030 // value. | 4027 // value. |
| 4031 __ Ret(); | 4028 __ Ret(); |
| 4032 | 4029 |
| 4033 __ bind(&nan_or_infinity_or_zero); | 4030 __ bind(&nan_or_infinity_or_zero); |
| 4034 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); | 4031 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); |
| 4035 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); | 4032 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); |
| 4036 __ orr(r9, r9, r7); | 4033 __ orr(r9, r9, r7); |
| 4037 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); | 4034 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); |
| 4038 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); | 4035 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); |
| 4039 __ b(&done); | 4036 __ b(&done); |
| 4040 } else if (array_type == kExternalDoubleArray) { | 4037 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 4041 __ add(r7, r3, Operand(r4, LSL, 3)); | 4038 __ add(r7, r3, Operand(r4, LSL, 3)); |
| 4042 // r7: effective address of destination element. | 4039 // r7: effective address of destination element. |
| 4043 __ str(r6, MemOperand(r7, 0)); | 4040 __ str(r6, MemOperand(r7, 0)); |
| 4044 __ str(r5, MemOperand(r7, Register::kSizeInBytes)); | 4041 __ str(r5, MemOperand(r7, Register::kSizeInBytes)); |
| 4045 __ Ret(); | 4042 __ Ret(); |
| 4046 } else { | 4043 } else { |
| 4047 bool is_signed_type = IsElementTypeSigned(array_type); | 4044 bool is_signed_type = IsElementTypeSigned(elements_kind); |
| 4048 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; | 4045 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; |
| 4049 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; | 4046 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; |
| 4050 | 4047 |
| 4051 Label done, sign; | 4048 Label done, sign; |
| 4052 | 4049 |
| 4053 // Test for all special exponent values: zeros, subnormal numbers, NaNs | 4050 // Test for all special exponent values: zeros, subnormal numbers, NaNs |
| 4054 // and infinities. All these should be converted to 0. | 4051 // and infinities. All these should be converted to 0. |
| 4055 __ mov(r7, Operand(HeapNumber::kExponentMask)); | 4052 __ mov(r7, Operand(HeapNumber::kExponentMask)); |
| 4056 __ and_(r9, r5, Operand(r7), SetCC); | 4053 __ and_(r9, r5, Operand(r7), SetCC); |
| 4057 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); | 4054 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4084 __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); | 4081 __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); |
| 4085 __ mov(r5, Operand(r5, LSL, r9)); | 4082 __ mov(r5, Operand(r5, LSL, r9)); |
| 4086 __ rsb(r9, r9, Operand(meaningfull_bits)); | 4083 __ rsb(r9, r9, Operand(meaningfull_bits)); |
| 4087 __ orr(r5, r5, Operand(r6, LSR, r9)); | 4084 __ orr(r5, r5, Operand(r6, LSR, r9)); |
| 4088 | 4085 |
| 4089 __ bind(&sign); | 4086 __ bind(&sign); |
| 4090 __ teq(r7, Operand(0, RelocInfo::NONE)); | 4087 __ teq(r7, Operand(0, RelocInfo::NONE)); |
| 4091 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 4088 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| 4092 | 4089 |
| 4093 __ bind(&done); | 4090 __ bind(&done); |
| 4094 switch (array_type) { | 4091 switch (elements_kind) { |
| 4095 case kExternalByteArray: | 4092 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 4096 case kExternalUnsignedByteArray: | 4093 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4097 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 4094 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 4098 break; | 4095 break; |
| 4099 case kExternalShortArray: | 4096 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 4100 case kExternalUnsignedShortArray: | 4097 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4101 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | 4098 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| 4102 break; | 4099 break; |
| 4103 case kExternalIntArray: | 4100 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 4104 case kExternalUnsignedIntArray: | 4101 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4105 __ str(r5, MemOperand(r3, r4, LSL, 2)); | 4102 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| 4106 break; | 4103 break; |
| 4107 default: | 4104 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 4105 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 4106 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 4107 case JSObject::FAST_ELEMENTS: |
| 4108 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 4109 case JSObject::DICTIONARY_ELEMENTS: |
| 4110 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4108 UNREACHABLE(); | 4111 UNREACHABLE(); |
| 4109 break; | 4112 break; |
| 4110 } | 4113 } |
| 4111 } | 4114 } |
| 4112 } | 4115 } |
| 4113 } | 4116 } |
| 4114 | 4117 |
| 4115 // Slow case, key and receiver still in r0 and r1. | 4118 // Slow case, key and receiver still in r0 and r1. |
| 4116 __ bind(&slow); | 4119 __ bind(&slow); |
| 4117 __ IncrementCounter( | 4120 __ IncrementCounter( |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4198 Register value_reg = r0; | 4201 Register value_reg = r0; |
| 4199 Register key_reg = r1; | 4202 Register key_reg = r1; |
| 4200 Register receiver_reg = r2; | 4203 Register receiver_reg = r2; |
| 4201 Register scratch = r3; | 4204 Register scratch = r3; |
| 4202 Register elements_reg = r4; | 4205 Register elements_reg = r4; |
| 4203 | 4206 |
| 4204 // This stub is meant to be tail-jumped to, the receiver must already | 4207 // This stub is meant to be tail-jumped to, the receiver must already |
| 4205 // have been verified by the caller to not be a smi. | 4208 // have been verified by the caller to not be a smi. |
| 4206 | 4209 |
| 4207 // Check that the key is a smi. | 4210 // Check that the key is a smi. |
| 4208 __ JumpIfNotSmi(r0, &miss_force_generic); | 4211 __ JumpIfNotSmi(key_reg, &miss_force_generic); |
| 4209 | 4212 |
| 4210 // Get the elements array and make sure it is a fast element array, not 'cow'. | 4213 // Get the elements array and make sure it is a fast element array, not 'cow'. |
| 4211 __ ldr(elements_reg, | 4214 __ ldr(elements_reg, |
| 4212 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); | 4215 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); |
| 4213 __ CheckMap(elements_reg, | 4216 __ CheckMap(elements_reg, |
| 4214 scratch, | 4217 scratch, |
| 4215 Heap::kFixedArrayMapRootIndex, | 4218 Heap::kFixedArrayMapRootIndex, |
| 4216 &miss_force_generic, | 4219 &miss_force_generic, |
| 4217 DONT_DO_SMI_CHECK); | 4220 DONT_DO_SMI_CHECK); |
| 4218 | 4221 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4249 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4252 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4250 __ Jump(ic, RelocInfo::CODE_TARGET); | 4253 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 4251 } | 4254 } |
| 4252 | 4255 |
| 4253 | 4256 |
| 4254 #undef __ | 4257 #undef __ |
| 4255 | 4258 |
| 4256 } } // namespace v8::internal | 4259 } } // namespace v8::internal |
| 4257 | 4260 |
| 4258 #endif // V8_TARGET_ARCH_ARM | 4261 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |