| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 315 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 316 } | 316 } |
| 317 | 317 |
| 318 | 318 |
| 319 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 319 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 320 Register dst, | 320 Register dst, |
| 321 Register src, | 321 Register src, |
| 322 bool inobject, | 322 bool inobject, |
| 323 int index, | 323 int index, |
| 324 Representation representation) { | 324 Representation representation) { |
| 325 ASSERT(!FLAG_track_double_fields || !representation.IsDouble()); | 325 ASSERT(!representation.IsDouble()); |
| 326 int offset = index * kPointerSize; | 326 int offset = index * kPointerSize; |
| 327 if (!inobject) { | 327 if (!inobject) { |
| 328 // Calculate the offset into the properties array. | 328 // Calculate the offset into the properties array. |
| 329 offset = offset + FixedArray::kHeaderSize; | 329 offset = offset + FixedArray::kHeaderSize; |
| 330 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | 330 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
| 331 src = dst; | 331 src = dst; |
| 332 } | 332 } |
| 333 __ ldr(dst, FieldMemOperand(src, offset)); | 333 __ ldr(dst, FieldMemOperand(src, offset)); |
| 334 } | 334 } |
| 335 | 335 |
| 336 | 336 |
| 337 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 337 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
| 338 Register receiver, | 338 Register receiver, |
| 339 Register scratch, | 339 Register scratch, |
| 340 Label* miss_label) { | 340 Label* miss_label) { |
| 341 // Check that the receiver isn't a smi. | 341 // Check that the receiver isn't a smi. |
| 342 __ JumpIfSmi(receiver, miss_label); | 342 __ JumpIfSmi(receiver, miss_label); |
| 343 | 343 |
| 344 // Check that the object is a JS array. | 344 // Check that the object is a JS array. |
| 345 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); | 345 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); |
| 346 __ b(ne, miss_label); | 346 __ b(ne, miss_label); |
| 347 | 347 |
| 348 // Load length directly from the JS array. | 348 // Load length directly from the JS array. |
| 349 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 349 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 350 __ Ret(); | 350 __ Ret(); |
| 351 } | 351 } |
| 352 | 352 |
| 353 | 353 |
| 354 // Generate code to check if an object is a string. If the object is a | |
| 355 // heap object, its map's instance type is left in the scratch1 register. | |
| 356 // If this is not needed, scratch1 and scratch2 may be the same register. | |
| 357 static void GenerateStringCheck(MacroAssembler* masm, | |
| 358 Register receiver, | |
| 359 Register scratch1, | |
| 360 Register scratch2, | |
| 361 Label* smi, | |
| 362 Label* non_string_object) { | |
| 363 // Check that the receiver isn't a smi. | |
| 364 __ JumpIfSmi(receiver, smi); | |
| 365 | |
| 366 // Check that the object is a string. | |
| 367 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
| 368 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | |
| 369 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); | |
| 370 // The cast is to resolve the overload for the argument of 0x0. | |
| 371 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); | |
| 372 __ b(ne, non_string_object); | |
| 373 } | |
| 374 | |
| 375 | |
| 376 // Generate code to load the length from a string object and return the length. | |
| 377 // If the receiver object is not a string or a wrapped string object the | |
| 378 // execution continues at the miss label. The register containing the | |
| 379 // receiver is potentially clobbered. | |
| 380 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | |
| 381 Register receiver, | |
| 382 Register scratch1, | |
| 383 Register scratch2, | |
| 384 Label* miss) { | |
| 385 Label check_wrapper; | |
| 386 | |
| 387 // Check if the object is a string leaving the instance type in the | |
| 388 // scratch1 register. | |
| 389 GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper); | |
| 390 | |
| 391 // Load length directly from the string. | |
| 392 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset)); | |
| 393 __ Ret(); | |
| 394 | |
| 395 // Check if the object is a JSValue wrapper. | |
| 396 __ bind(&check_wrapper); | |
| 397 __ cmp(scratch1, Operand(JS_VALUE_TYPE)); | |
| 398 __ b(ne, miss); | |
| 399 | |
| 400 // Unwrap the value and check if the wrapped value is a string. | |
| 401 __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); | |
| 402 GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss); | |
| 403 __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset)); | |
| 404 __ Ret(); | |
| 405 } | |
| 406 | |
| 407 | |
| 408 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 354 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
| 409 Register receiver, | 355 Register receiver, |
| 410 Register scratch1, | 356 Register scratch1, |
| 411 Register scratch2, | 357 Register scratch2, |
| 412 Label* miss_label) { | 358 Label* miss_label) { |
| 413 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 359 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 414 __ mov(r0, scratch1); | 360 __ mov(r0, scratch1); |
| 415 __ Ret(); | 361 __ Ret(); |
| 416 } | 362 } |
| 417 | 363 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 DescriptorArray* descriptors = transition->instance_descriptors(); | 420 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 475 PropertyDetails details = descriptors->GetDetails(descriptor); | 421 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 476 Representation representation = details.representation(); | 422 Representation representation = details.representation(); |
| 477 ASSERT(!representation.IsNone()); | 423 ASSERT(!representation.IsNone()); |
| 478 | 424 |
| 479 if (details.type() == CONSTANT) { | 425 if (details.type() == CONSTANT) { |
| 480 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 426 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
| 481 __ Move(scratch1, constant); | 427 __ Move(scratch1, constant); |
| 482 __ cmp(value_reg, scratch1); | 428 __ cmp(value_reg, scratch1); |
| 483 __ b(ne, miss_label); | 429 __ b(ne, miss_label); |
| 484 } else if (FLAG_track_fields && representation.IsSmi()) { | 430 } else if (representation.IsSmi()) { |
| 485 __ JumpIfNotSmi(value_reg, miss_label); | 431 __ JumpIfNotSmi(value_reg, miss_label); |
| 486 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 432 } else if (representation.IsHeapObject()) { |
| 487 __ JumpIfSmi(value_reg, miss_label); | 433 __ JumpIfSmi(value_reg, miss_label); |
| 488 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 434 } else if (representation.IsDouble()) { |
| 489 Label do_store, heap_number; | 435 Label do_store, heap_number; |
| 490 __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex); | 436 __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex); |
| 491 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow); | 437 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow); |
| 492 | 438 |
| 493 __ JumpIfNotSmi(value_reg, &heap_number); | 439 __ JumpIfNotSmi(value_reg, &heap_number); |
| 494 __ SmiUntag(scratch1, value_reg); | 440 __ SmiUntag(scratch1, value_reg); |
| 495 __ vmov(s0, scratch1); | 441 __ vmov(s0, scratch1); |
| 496 __ vcvt_f64_s32(d0, s0); | 442 __ vcvt_f64_s32(d0, s0); |
| 497 __ jmp(&do_store); | 443 __ jmp(&do_store); |
| 498 | 444 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 // face of a transition we can use the old map here because the size of the | 498 // face of a transition we can use the old map here because the size of the |
| 553 // object and the number of in-object properties is not going to change. | 499 // object and the number of in-object properties is not going to change. |
| 554 index -= object->map()->inobject_properties(); | 500 index -= object->map()->inobject_properties(); |
| 555 | 501 |
| 556 // TODO(verwaest): Share this code as a code stub. | 502 // TODO(verwaest): Share this code as a code stub. |
| 557 SmiCheck smi_check = representation.IsTagged() | 503 SmiCheck smi_check = representation.IsTagged() |
| 558 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 504 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 559 if (index < 0) { | 505 if (index < 0) { |
| 560 // Set the property straight into the object. | 506 // Set the property straight into the object. |
| 561 int offset = object->map()->instance_size() + (index * kPointerSize); | 507 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 562 if (FLAG_track_double_fields && representation.IsDouble()) { | 508 if (representation.IsDouble()) { |
| 563 __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); | 509 __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); |
| 564 } else { | 510 } else { |
| 565 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); | 511 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
| 566 } | 512 } |
| 567 | 513 |
| 568 if (!FLAG_track_fields || !representation.IsSmi()) { | 514 if (!representation.IsSmi()) { |
| 569 // Update the write barrier for the array address. | 515 // Update the write barrier for the array address. |
| 570 if (!FLAG_track_double_fields || !representation.IsDouble()) { | 516 if (!representation.IsDouble()) { |
| 571 __ mov(storage_reg, value_reg); | 517 __ mov(storage_reg, value_reg); |
| 572 } | 518 } |
| 573 __ RecordWriteField(receiver_reg, | 519 __ RecordWriteField(receiver_reg, |
| 574 offset, | 520 offset, |
| 575 storage_reg, | 521 storage_reg, |
| 576 scratch1, | 522 scratch1, |
| 577 kLRHasNotBeenSaved, | 523 kLRHasNotBeenSaved, |
| 578 kDontSaveFPRegs, | 524 kDontSaveFPRegs, |
| 579 EMIT_REMEMBERED_SET, | 525 EMIT_REMEMBERED_SET, |
| 580 smi_check); | 526 smi_check); |
| 581 } | 527 } |
| 582 } else { | 528 } else { |
| 583 // Write to the properties array. | 529 // Write to the properties array. |
| 584 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 530 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 585 // Get the properties array | 531 // Get the properties array |
| 586 __ ldr(scratch1, | 532 __ ldr(scratch1, |
| 587 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 533 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 588 if (FLAG_track_double_fields && representation.IsDouble()) { | 534 if (representation.IsDouble()) { |
| 589 __ str(storage_reg, FieldMemOperand(scratch1, offset)); | 535 __ str(storage_reg, FieldMemOperand(scratch1, offset)); |
| 590 } else { | 536 } else { |
| 591 __ str(value_reg, FieldMemOperand(scratch1, offset)); | 537 __ str(value_reg, FieldMemOperand(scratch1, offset)); |
| 592 } | 538 } |
| 593 | 539 |
| 594 if (!FLAG_track_fields || !representation.IsSmi()) { | 540 if (!representation.IsSmi()) { |
| 595 // Update the write barrier for the array address. | 541 // Update the write barrier for the array address. |
| 596 if (!FLAG_track_double_fields || !representation.IsDouble()) { | 542 if (!representation.IsDouble()) { |
| 597 __ mov(storage_reg, value_reg); | 543 __ mov(storage_reg, value_reg); |
| 598 } | 544 } |
| 599 __ RecordWriteField(scratch1, | 545 __ RecordWriteField(scratch1, |
| 600 offset, | 546 offset, |
| 601 storage_reg, | 547 storage_reg, |
| 602 receiver_reg, | 548 receiver_reg, |
| 603 kLRHasNotBeenSaved, | 549 kLRHasNotBeenSaved, |
| 604 kDontSaveFPRegs, | 550 kDontSaveFPRegs, |
| 605 EMIT_REMEMBERED_SET, | 551 EMIT_REMEMBERED_SET, |
| 606 smi_check); | 552 smi_check); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 636 | 582 |
| 637 int index = lookup->GetFieldIndex().field_index(); | 583 int index = lookup->GetFieldIndex().field_index(); |
| 638 | 584 |
| 639 // Adjust for the number of properties stored in the object. Even in the | 585 // Adjust for the number of properties stored in the object. Even in the |
| 640 // face of a transition we can use the old map here because the size of the | 586 // face of a transition we can use the old map here because the size of the |
| 641 // object and the number of in-object properties is not going to change. | 587 // object and the number of in-object properties is not going to change. |
| 642 index -= object->map()->inobject_properties(); | 588 index -= object->map()->inobject_properties(); |
| 643 | 589 |
| 644 Representation representation = lookup->representation(); | 590 Representation representation = lookup->representation(); |
| 645 ASSERT(!representation.IsNone()); | 591 ASSERT(!representation.IsNone()); |
| 646 if (FLAG_track_fields && representation.IsSmi()) { | 592 if (representation.IsSmi()) { |
| 647 __ JumpIfNotSmi(value_reg, miss_label); | 593 __ JumpIfNotSmi(value_reg, miss_label); |
| 648 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 594 } else if (representation.IsHeapObject()) { |
| 649 __ JumpIfSmi(value_reg, miss_label); | 595 __ JumpIfSmi(value_reg, miss_label); |
| 650 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 596 } else if (representation.IsDouble()) { |
| 651 // Load the double storage. | 597 // Load the double storage. |
| 652 if (index < 0) { | 598 if (index < 0) { |
| 653 int offset = object->map()->instance_size() + (index * kPointerSize); | 599 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 654 __ ldr(scratch1, FieldMemOperand(receiver_reg, offset)); | 600 __ ldr(scratch1, FieldMemOperand(receiver_reg, offset)); |
| 655 } else { | 601 } else { |
| 656 __ ldr(scratch1, | 602 __ ldr(scratch1, |
| 657 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 603 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 658 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 604 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 659 __ ldr(scratch1, FieldMemOperand(scratch1, offset)); | 605 __ ldr(scratch1, FieldMemOperand(scratch1, offset)); |
| 660 } | 606 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 681 } | 627 } |
| 682 | 628 |
| 683 // TODO(verwaest): Share this code as a code stub. | 629 // TODO(verwaest): Share this code as a code stub. |
| 684 SmiCheck smi_check = representation.IsTagged() | 630 SmiCheck smi_check = representation.IsTagged() |
| 685 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 631 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 686 if (index < 0) { | 632 if (index < 0) { |
| 687 // Set the property straight into the object. | 633 // Set the property straight into the object. |
| 688 int offset = object->map()->instance_size() + (index * kPointerSize); | 634 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 689 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); | 635 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
| 690 | 636 |
| 691 if (!FLAG_track_fields || !representation.IsSmi()) { | 637 if (!representation.IsSmi()) { |
| 692 // Skip updating write barrier if storing a smi. | 638 // Skip updating write barrier if storing a smi. |
| 693 __ JumpIfSmi(value_reg, &exit); | 639 __ JumpIfSmi(value_reg, &exit); |
| 694 | 640 |
| 695 // Update the write barrier for the array address. | 641 // Update the write barrier for the array address. |
| 696 // Pass the now unused name_reg as a scratch register. | 642 // Pass the now unused name_reg as a scratch register. |
| 697 __ mov(name_reg, value_reg); | 643 __ mov(name_reg, value_reg); |
| 698 __ RecordWriteField(receiver_reg, | 644 __ RecordWriteField(receiver_reg, |
| 699 offset, | 645 offset, |
| 700 name_reg, | 646 name_reg, |
| 701 scratch1, | 647 scratch1, |
| 702 kLRHasNotBeenSaved, | 648 kLRHasNotBeenSaved, |
| 703 kDontSaveFPRegs, | 649 kDontSaveFPRegs, |
| 704 EMIT_REMEMBERED_SET, | 650 EMIT_REMEMBERED_SET, |
| 705 smi_check); | 651 smi_check); |
| 706 } | 652 } |
| 707 } else { | 653 } else { |
| 708 // Write to the properties array. | 654 // Write to the properties array. |
| 709 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 655 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 710 // Get the properties array | 656 // Get the properties array |
| 711 __ ldr(scratch1, | 657 __ ldr(scratch1, |
| 712 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 658 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 713 __ str(value_reg, FieldMemOperand(scratch1, offset)); | 659 __ str(value_reg, FieldMemOperand(scratch1, offset)); |
| 714 | 660 |
| 715 if (!FLAG_track_fields || !representation.IsSmi()) { | 661 if (!representation.IsSmi()) { |
| 716 // Skip updating write barrier if storing a smi. | 662 // Skip updating write barrier if storing a smi. |
| 717 __ JumpIfSmi(value_reg, &exit); | 663 __ JumpIfSmi(value_reg, &exit); |
| 718 | 664 |
| 719 // Update the write barrier for the array address. | 665 // Update the write barrier for the array address. |
| 720 // Ok to clobber receiver_reg and name_reg, since we return. | 666 // Ok to clobber receiver_reg and name_reg, since we return. |
| 721 __ mov(name_reg, value_reg); | 667 __ mov(name_reg, value_reg); |
| 722 __ RecordWriteField(scratch1, | 668 __ RecordWriteField(scratch1, |
| 723 offset, | 669 offset, |
| 724 name_reg, | 670 name_reg, |
| 725 receiver_reg, | 671 receiver_reg, |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 // the holder and it is needed should the interceptor return without any | 1101 // the holder and it is needed should the interceptor return without any |
| 1156 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 1102 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
| 1157 // the FIELD case might cause a miss during the prototype check. | 1103 // the FIELD case might cause a miss during the prototype check. |
| 1158 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); | 1104 bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); |
| 1159 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 1105 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
| 1160 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 1106 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
| 1161 | 1107 |
| 1162 // Save necessary data before invoking an interceptor. | 1108 // Save necessary data before invoking an interceptor. |
| 1163 // Requires a frame to make GC aware of pushed pointers. | 1109 // Requires a frame to make GC aware of pushed pointers. |
| 1164 { | 1110 { |
| 1165 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1111 FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1166 if (must_preserve_receiver_reg) { | 1112 if (must_preserve_receiver_reg) { |
| 1167 __ Push(receiver(), holder_reg, this->name()); | 1113 __ Push(receiver(), holder_reg, this->name()); |
| 1168 } else { | 1114 } else { |
| 1169 __ Push(holder_reg, this->name()); | 1115 __ Push(holder_reg, this->name()); |
| 1170 } | 1116 } |
| 1171 // Invoke an interceptor. Note: map checks from receiver to | 1117 // Invoke an interceptor. Note: map checks from receiver to |
| 1172 // interceptor's holder has been compiled before (see a caller | 1118 // interceptor's holder has been compiled before (see a caller |
| 1173 // of this method.) | 1119 // of this method.) |
| 1174 CompileCallLoadPropertyWithInterceptor( | 1120 CompileCallLoadPropertyWithInterceptor( |
| 1175 masm(), receiver(), holder_reg, this->name(), interceptor_holder, | 1121 masm(), receiver(), holder_reg, this->name(), interceptor_holder, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 } | 1195 } |
| 1250 | 1196 |
| 1251 | 1197 |
| 1252 #undef __ | 1198 #undef __ |
| 1253 #define __ ACCESS_MASM(masm) | 1199 #define __ ACCESS_MASM(masm) |
| 1254 | 1200 |
| 1255 | 1201 |
| 1256 void StoreStubCompiler::GenerateStoreViaSetter( | 1202 void StoreStubCompiler::GenerateStoreViaSetter( |
| 1257 MacroAssembler* masm, | 1203 MacroAssembler* masm, |
| 1258 Handle<HeapType> type, | 1204 Handle<HeapType> type, |
| 1205 Register receiver, |
| 1259 Handle<JSFunction> setter) { | 1206 Handle<JSFunction> setter) { |
| 1260 // ----------- S t a t e ------------- | 1207 // ----------- S t a t e ------------- |
| 1261 // -- r0 : value | |
| 1262 // -- r1 : receiver | |
| 1263 // -- r2 : name | |
| 1264 // -- lr : return address | 1208 // -- lr : return address |
| 1265 // ----------------------------------- | 1209 // ----------------------------------- |
| 1266 { | 1210 { |
| 1267 FrameScope scope(masm, StackFrame::INTERNAL); | 1211 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1268 Register receiver = r1; | |
| 1269 Register value = r0; | |
| 1270 | 1212 |
| 1271 // Save value register, so we can restore it later. | 1213 // Save value register, so we can restore it later. |
| 1272 __ push(value); | 1214 __ push(value()); |
| 1273 | 1215 |
| 1274 if (!setter.is_null()) { | 1216 if (!setter.is_null()) { |
| 1275 // Call the JavaScript setter with receiver and value on the stack. | 1217 // Call the JavaScript setter with receiver and value on the stack. |
| 1276 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 1218 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 1277 // Swap in the global receiver. | 1219 // Swap in the global receiver. |
| 1278 __ ldr(receiver, | 1220 __ ldr(receiver, |
| 1279 FieldMemOperand( | 1221 FieldMemOperand( |
| 1280 receiver, JSGlobalObject::kGlobalReceiverOffset)); | 1222 receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 1281 } | 1223 } |
| 1282 __ Push(receiver, value); | 1224 __ Push(receiver, value()); |
| 1283 ParameterCount actual(1); | 1225 ParameterCount actual(1); |
| 1284 ParameterCount expected(setter); | 1226 ParameterCount expected(setter); |
| 1285 __ InvokeFunction(setter, expected, actual, | 1227 __ InvokeFunction(setter, expected, actual, |
| 1286 CALL_FUNCTION, NullCallWrapper()); | 1228 CALL_FUNCTION, NullCallWrapper()); |
| 1287 } else { | 1229 } else { |
| 1288 // If we generate a global code snippet for deoptimization only, remember | 1230 // If we generate a global code snippet for deoptimization only, remember |
| 1289 // the place to continue after deoptimization. | 1231 // the place to continue after deoptimization. |
| 1290 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | 1232 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
| 1291 } | 1233 } |
| 1292 | 1234 |
| 1293 // We have to return the passed value, not the return value of the setter. | 1235 // We have to return the passed value, not the return value of the setter. |
| 1294 __ pop(r0); | 1236 __ pop(r0); |
| 1295 | 1237 |
| 1296 // Restore context register. | 1238 // Restore context register. |
| 1297 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1239 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1298 } | 1240 } |
| 1299 __ Ret(); | 1241 __ Ret(); |
| 1300 } | 1242 } |
| 1301 | 1243 |
| 1302 | 1244 |
| 1303 #undef __ | 1245 #undef __ |
| 1304 #define __ ACCESS_MASM(masm()) | 1246 #define __ ACCESS_MASM(masm()) |
| 1305 | 1247 |
| 1306 | 1248 |
| 1307 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1249 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 1308 Handle<JSObject> object, | 1250 Handle<JSObject> object, |
| 1309 Handle<Name> name) { | 1251 Handle<Name> name) { |
| 1310 Label miss; | |
| 1311 | |
| 1312 // Check that the map of the object hasn't changed. | |
| 1313 __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss, | |
| 1314 DO_SMI_CHECK); | |
| 1315 | |
| 1316 // Perform global security token check if needed. | |
| 1317 if (object->IsJSGlobalProxy()) { | |
| 1318 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); | |
| 1319 } | |
| 1320 | |
| 1321 // Stub is never generated for non-global objects that require access | |
| 1322 // checks. | |
| 1323 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 1324 | |
| 1325 __ Push(receiver(), this->name(), value()); | 1252 __ Push(receiver(), this->name(), value()); |
| 1326 | 1253 |
| 1327 // Do tail-call to the runtime system. | 1254 // Do tail-call to the runtime system. |
| 1328 ExternalReference store_ic_property = | 1255 ExternalReference store_ic_property = |
| 1329 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1256 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 1330 __ TailCallExternalReference(store_ic_property, 3, 1); | 1257 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 1331 | 1258 |
| 1332 // Handle store cache miss. | |
| 1333 __ bind(&miss); | |
| 1334 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 1335 | |
| 1336 // Return the generated code. | 1259 // Return the generated code. |
| 1337 return GetCode(kind(), Code::FAST, name); | 1260 return GetCode(kind(), Code::FAST, name); |
| 1338 } | 1261 } |
| 1339 | 1262 |
| 1340 | 1263 |
| 1341 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1264 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, |
| 1342 Handle<JSObject> last, | 1265 Handle<JSObject> last, |
| 1343 Handle<Name> name) { | 1266 Handle<Name> name) { |
| 1344 NonexistentHandlerFrontend(type, last, name); | 1267 NonexistentHandlerFrontend(type, last, name); |
| 1345 | 1268 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1360 } | 1283 } |
| 1361 | 1284 |
| 1362 | 1285 |
| 1363 Register* KeyedLoadStubCompiler::registers() { | 1286 Register* KeyedLoadStubCompiler::registers() { |
| 1364 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1287 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 1365 static Register registers[] = { r1, r0, r2, r3, r4, r5 }; | 1288 static Register registers[] = { r1, r0, r2, r3, r4, r5 }; |
| 1366 return registers; | 1289 return registers; |
| 1367 } | 1290 } |
| 1368 | 1291 |
| 1369 | 1292 |
| 1293 Register StoreStubCompiler::value() { |
| 1294 return r0; |
| 1295 } |
| 1296 |
| 1297 |
| 1370 Register* StoreStubCompiler::registers() { | 1298 Register* StoreStubCompiler::registers() { |
| 1371 // receiver, name, value, scratch1, scratch2, scratch3. | 1299 // receiver, name, scratch1, scratch2, scratch3. |
| 1372 static Register registers[] = { r1, r2, r0, r3, r4, r5 }; | 1300 static Register registers[] = { r1, r2, r3, r4, r5 }; |
| 1373 return registers; | 1301 return registers; |
| 1374 } | 1302 } |
| 1375 | 1303 |
| 1376 | 1304 |
| 1377 Register* KeyedStoreStubCompiler::registers() { | 1305 Register* KeyedStoreStubCompiler::registers() { |
| 1378 // receiver, name, value, scratch1, scratch2, scratch3. | 1306 // receiver, name, scratch1, scratch2, scratch3. |
| 1379 static Register registers[] = { r2, r1, r0, r3, r4, r5 }; | 1307 static Register registers[] = { r2, r1, r3, r4, r5 }; |
| 1380 return registers; | 1308 return registers; |
| 1381 } | 1309 } |
| 1382 | 1310 |
| 1383 | 1311 |
| 1384 #undef __ | 1312 #undef __ |
| 1385 #define __ ACCESS_MASM(masm) | 1313 #define __ ACCESS_MASM(masm) |
| 1386 | 1314 |
| 1387 | 1315 |
| 1388 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1316 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 1389 Handle<HeapType> type, | 1317 Handle<HeapType> type, |
| 1390 Register receiver, | 1318 Register receiver, |
| 1391 Handle<JSFunction> getter) { | 1319 Handle<JSFunction> getter) { |
| 1392 // ----------- S t a t e ------------- | 1320 // ----------- S t a t e ------------- |
| 1393 // -- r0 : receiver | 1321 // -- r0 : receiver |
| 1394 // -- r2 : name | 1322 // -- r2 : name |
| 1395 // -- lr : return address | 1323 // -- lr : return address |
| 1396 // ----------------------------------- | 1324 // ----------------------------------- |
| 1397 { | 1325 { |
| 1398 FrameScope scope(masm, StackFrame::INTERNAL); | 1326 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1399 | 1327 |
| 1400 if (!getter.is_null()) { | 1328 if (!getter.is_null()) { |
| 1401 // Call the JavaScript getter with the receiver on the stack. | 1329 // Call the JavaScript getter with the receiver on the stack. |
| 1402 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 1330 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 1403 // Swap in the global receiver. | 1331 // Swap in the global receiver. |
| 1404 __ ldr(receiver, | 1332 __ ldr(receiver, |
| 1405 FieldMemOperand( | 1333 FieldMemOperand( |
| 1406 receiver, JSGlobalObject::kGlobalReceiverOffset)); | 1334 receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 1407 } | 1335 } |
| 1408 __ push(receiver); | 1336 __ push(receiver); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 // ----------------------------------- | 1511 // ----------------------------------- |
| 1584 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1512 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1585 } | 1513 } |
| 1586 | 1514 |
| 1587 | 1515 |
| 1588 #undef __ | 1516 #undef __ |
| 1589 | 1517 |
| 1590 } } // namespace v8::internal | 1518 } } // namespace v8::internal |
| 1591 | 1519 |
| 1592 #endif // V8_TARGET_ARCH_ARM | 1520 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |