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 |