| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 4387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4398 // sp[0] = right string | 4398 // sp[0] = right string |
| 4399 // sp[8] = left string. | 4399 // sp[8] = left string. |
| 4400 __ Push(left, right); | 4400 __ Push(left, right); |
| 4401 | 4401 |
| 4402 // Call the runtime. | 4402 // Call the runtime. |
| 4403 // Returns -1 (less), 0 (equal), or 1 (greater) tagged as a small integer. | 4403 // Returns -1 (less), 0 (equal), or 1 (greater) tagged as a small integer. |
| 4404 __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); | 4404 __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); |
| 4405 } | 4405 } |
| 4406 | 4406 |
| 4407 | 4407 |
| 4408 void ArrayPushStub::Generate(MacroAssembler* masm) { | |
| 4409 Register receiver = x0; | |
| 4410 | |
| 4411 int argc = arguments_count(); | |
| 4412 | |
| 4413 if (argc == 0) { | |
| 4414 // Nothing to do, just return the length. | |
| 4415 __ Ldr(x0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 4416 __ Drop(argc + 1); | |
| 4417 __ Ret(); | |
| 4418 return; | |
| 4419 } | |
| 4420 | |
| 4421 Isolate* isolate = masm->isolate(); | |
| 4422 | |
| 4423 if (argc != 1) { | |
| 4424 __ TailCallExternalReference( | |
| 4425 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
| 4426 return; | |
| 4427 } | |
| 4428 | |
| 4429 Label call_builtin, attempt_to_grow_elements, with_write_barrier; | |
| 4430 | |
| 4431 Register elements_length = x8; | |
| 4432 Register length = x7; | |
| 4433 Register elements = x6; | |
| 4434 Register end_elements = x5; | |
| 4435 Register value = x4; | |
| 4436 // Get the elements array of the object. | |
| 4437 __ Ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | |
| 4438 | |
| 4439 if (IsFastSmiOrObjectElementsKind(elements_kind())) { | |
| 4440 // Check that the elements are in fast mode and writable. | |
| 4441 __ CheckMap(elements, | |
| 4442 x10, | |
| 4443 Heap::kFixedArrayMapRootIndex, | |
| 4444 &call_builtin, | |
| 4445 DONT_DO_SMI_CHECK); | |
| 4446 } | |
| 4447 | |
| 4448 // Get the array's length and calculate new length. | |
| 4449 __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 4450 STATIC_ASSERT(kSmiTag == 0); | |
| 4451 __ Add(length, length, Smi::FromInt(argc)); | |
| 4452 | |
| 4453 // Check if we could survive without allocation. | |
| 4454 __ Ldr(elements_length, | |
| 4455 FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 4456 __ Cmp(length, elements_length); | |
| 4457 | |
| 4458 const int kEndElementsOffset = | |
| 4459 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | |
| 4460 | |
| 4461 if (IsFastSmiOrObjectElementsKind(elements_kind())) { | |
| 4462 __ B(gt, &attempt_to_grow_elements); | |
| 4463 | |
| 4464 // Check if value is a smi. | |
| 4465 __ Peek(value, (argc - 1) * kPointerSize); | |
| 4466 __ JumpIfNotSmi(value, &with_write_barrier); | |
| 4467 | |
| 4468 // Store the value. | |
| 4469 // We may need a register containing the address end_elements below, | |
| 4470 // so write back the value in end_elements. | |
| 4471 __ Add(end_elements, elements, | |
| 4472 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | |
| 4473 __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | |
| 4474 } else { | |
| 4475 __ B(gt, &call_builtin); | |
| 4476 | |
| 4477 __ Peek(value, (argc - 1) * kPointerSize); | |
| 4478 __ StoreNumberToDoubleElements(value, length, elements, x10, d0, d1, | |
| 4479 &call_builtin, argc * kDoubleSize); | |
| 4480 } | |
| 4481 | |
| 4482 // Save new length. | |
| 4483 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 4484 | |
| 4485 // Return length. | |
| 4486 __ Drop(argc + 1); | |
| 4487 __ Mov(x0, length); | |
| 4488 __ Ret(); | |
| 4489 | |
| 4490 if (IsFastDoubleElementsKind(elements_kind())) { | |
| 4491 __ Bind(&call_builtin); | |
| 4492 __ TailCallExternalReference( | |
| 4493 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
| 4494 return; | |
| 4495 } | |
| 4496 | |
| 4497 __ Bind(&with_write_barrier); | |
| 4498 | |
| 4499 if (IsFastSmiElementsKind(elements_kind())) { | |
| 4500 if (FLAG_trace_elements_transitions) { | |
| 4501 __ B(&call_builtin); | |
| 4502 } | |
| 4503 | |
| 4504 __ Ldr(x10, FieldMemOperand(value, HeapObject::kMapOffset)); | |
| 4505 __ JumpIfHeapNumber(x10, &call_builtin); | |
| 4506 | |
| 4507 ElementsKind target_kind = IsHoleyElementsKind(elements_kind()) | |
| 4508 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | |
| 4509 __ Ldr(x10, GlobalObjectMemOperand()); | |
| 4510 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kNativeContextOffset)); | |
| 4511 __ Ldr(x10, ContextMemOperand(x10, Context::JS_ARRAY_MAPS_INDEX)); | |
| 4512 const int header_size = FixedArrayBase::kHeaderSize; | |
| 4513 // Verify that the object can be transitioned in place. | |
| 4514 const int origin_offset = header_size + elements_kind() * kPointerSize; | |
| 4515 __ ldr(x11, FieldMemOperand(receiver, origin_offset)); | |
| 4516 __ ldr(x12, FieldMemOperand(x10, HeapObject::kMapOffset)); | |
| 4517 __ cmp(x11, x12); | |
| 4518 __ B(ne, &call_builtin); | |
| 4519 | |
| 4520 const int target_offset = header_size + target_kind * kPointerSize; | |
| 4521 __ Ldr(x10, FieldMemOperand(x10, target_offset)); | |
| 4522 __ Mov(x11, receiver); | |
| 4523 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | |
| 4524 masm, DONT_TRACK_ALLOCATION_SITE, NULL); | |
| 4525 } | |
| 4526 | |
| 4527 // Save new length. | |
| 4528 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 4529 | |
| 4530 // Store the value. | |
| 4531 // We may need a register containing the address end_elements below, | |
| 4532 // so write back the value in end_elements. | |
| 4533 __ Add(end_elements, elements, | |
| 4534 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | |
| 4535 __ Str(value, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | |
| 4536 | |
| 4537 __ RecordWrite(elements, | |
| 4538 end_elements, | |
| 4539 value, | |
| 4540 kLRHasNotBeenSaved, | |
| 4541 kDontSaveFPRegs, | |
| 4542 EMIT_REMEMBERED_SET, | |
| 4543 OMIT_SMI_CHECK); | |
| 4544 __ Drop(argc + 1); | |
| 4545 __ Mov(x0, length); | |
| 4546 __ Ret(); | |
| 4547 | |
| 4548 __ Bind(&attempt_to_grow_elements); | |
| 4549 | |
| 4550 if (!FLAG_inline_new) { | |
| 4551 __ B(&call_builtin); | |
| 4552 } | |
| 4553 | |
| 4554 Register argument = x2; | |
| 4555 __ Peek(argument, (argc - 1) * kPointerSize); | |
| 4556 // Growing elements that are SMI-only requires special handling in case | |
| 4557 // the new element is non-Smi. For now, delegate to the builtin. | |
| 4558 if (IsFastSmiElementsKind(elements_kind())) { | |
| 4559 __ JumpIfNotSmi(argument, &call_builtin); | |
| 4560 } | |
| 4561 | |
| 4562 // We could be lucky and the elements array could be at the top of new-space. | |
| 4563 // In this case we can just grow it in place by moving the allocation pointer | |
| 4564 // up. | |
| 4565 ExternalReference new_space_allocation_top = | |
| 4566 ExternalReference::new_space_allocation_top_address(isolate); | |
| 4567 ExternalReference new_space_allocation_limit = | |
| 4568 ExternalReference::new_space_allocation_limit_address(isolate); | |
| 4569 | |
| 4570 const int kAllocationDelta = 4; | |
| 4571 ASSERT(kAllocationDelta >= argc); | |
| 4572 Register allocation_top_addr = x5; | |
| 4573 Register allocation_top = x9; | |
| 4574 // Load top and check if it is the end of elements. | |
| 4575 __ Add(end_elements, elements, | |
| 4576 Operand::UntagSmiAndScale(length, kPointerSizeLog2)); | |
| 4577 __ Add(end_elements, end_elements, kEndElementsOffset); | |
| 4578 __ Mov(allocation_top_addr, new_space_allocation_top); | |
| 4579 __ Ldr(allocation_top, MemOperand(allocation_top_addr)); | |
| 4580 __ Cmp(end_elements, allocation_top); | |
| 4581 __ B(ne, &call_builtin); | |
| 4582 | |
| 4583 __ Mov(x10, new_space_allocation_limit); | |
| 4584 __ Ldr(x10, MemOperand(x10)); | |
| 4585 __ Add(allocation_top, allocation_top, kAllocationDelta * kPointerSize); | |
| 4586 __ Cmp(allocation_top, x10); | |
| 4587 __ B(hi, &call_builtin); | |
| 4588 | |
| 4589 // We fit and could grow elements. | |
| 4590 // Update new_space_allocation_top. | |
| 4591 __ Str(allocation_top, MemOperand(allocation_top_addr)); | |
| 4592 // Push the argument. | |
| 4593 __ Str(argument, MemOperand(end_elements)); | |
| 4594 // Fill the rest with holes. | |
| 4595 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); | |
| 4596 ASSERT(kAllocationDelta == 4); | |
| 4597 __ Stp(x10, x10, MemOperand(end_elements, 1 * kPointerSize)); | |
| 4598 __ Stp(x10, x10, MemOperand(end_elements, 3 * kPointerSize)); | |
| 4599 | |
| 4600 // Update elements' and array's sizes. | |
| 4601 __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
| 4602 __ Add(elements_length, elements_length, Smi::FromInt(kAllocationDelta)); | |
| 4603 __ Str(elements_length, | |
| 4604 FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 4605 | |
| 4606 // Elements are in new space, so write barrier is not required. | |
| 4607 __ Drop(argc + 1); | |
| 4608 __ Mov(x0, length); | |
| 4609 __ Ret(); | |
| 4610 | |
| 4611 __ Bind(&call_builtin); | |
| 4612 __ TailCallExternalReference( | |
| 4613 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
| 4614 } | |
| 4615 | |
| 4616 | |
| 4617 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 4408 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
| 4618 // ----------- S t a t e ------------- | 4409 // ----------- S t a t e ------------- |
| 4619 // -- x1 : left | 4410 // -- x1 : left |
| 4620 // -- x0 : right | 4411 // -- x0 : right |
| 4621 // -- lr : return address | 4412 // -- lr : return address |
| 4622 // ----------------------------------- | 4413 // ----------------------------------- |
| 4623 Isolate* isolate = masm->isolate(); | 4414 Isolate* isolate = masm->isolate(); |
| 4624 | 4415 |
| 4625 // Load x2 with the allocation site. We stick an undefined dummy value here | 4416 // Load x2 with the allocation site. We stick an undefined dummy value here |
| 4626 // and replace it with the real allocation site later when we instantiate this | 4417 // and replace it with the real allocation site later when we instantiate this |
| (...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5733 MemOperand(fp, 6 * kPointerSize), | 5524 MemOperand(fp, 6 * kPointerSize), |
| 5734 NULL); | 5525 NULL); |
| 5735 } | 5526 } |
| 5736 | 5527 |
| 5737 | 5528 |
| 5738 #undef __ | 5529 #undef __ |
| 5739 | 5530 |
| 5740 } } // namespace v8::internal | 5531 } } // namespace v8::internal |
| 5741 | 5532 |
| 5742 #endif // V8_TARGET_ARCH_ARM64 | 5533 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |