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 4395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4406 __ push(ecx); | 4406 __ push(ecx); |
4407 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 4407 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
4408 | 4408 |
4409 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 4409 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
4410 // tagged as a small integer. | 4410 // tagged as a small integer. |
4411 __ bind(&runtime); | 4411 __ bind(&runtime); |
4412 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4412 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
4413 } | 4413 } |
4414 | 4414 |
4415 | 4415 |
| 4416 void ArrayPushStub::Generate(MacroAssembler* masm) { |
| 4417 int argc = arguments_count(); |
| 4418 |
| 4419 if (argc == 0) { |
| 4420 // Noop, return the length. |
| 4421 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 4422 __ ret((argc + 1) * kPointerSize); |
| 4423 return; |
| 4424 } |
| 4425 |
| 4426 Isolate* isolate = masm->isolate(); |
| 4427 |
| 4428 if (argc != 1) { |
| 4429 __ TailCallExternalReference( |
| 4430 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4431 return; |
| 4432 } |
| 4433 |
| 4434 Label call_builtin, attempt_to_grow_elements, with_write_barrier; |
| 4435 |
| 4436 // Get the elements array of the object. |
| 4437 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); |
| 4438 |
| 4439 if (IsFastSmiOrObjectElementsKind(elements_kind())) { |
| 4440 // Check that the elements are in fast mode and writable. |
| 4441 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
| 4442 isolate->factory()->fixed_array_map()); |
| 4443 __ j(not_equal, &call_builtin); |
| 4444 } |
| 4445 |
| 4446 // Get the array's length into eax and calculate new length. |
| 4447 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 4448 STATIC_ASSERT(kSmiTagSize == 1); |
| 4449 STATIC_ASSERT(kSmiTag == 0); |
| 4450 __ add(eax, Immediate(Smi::FromInt(argc))); |
| 4451 |
| 4452 // Get the elements' length into ecx. |
| 4453 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
| 4454 |
| 4455 // Check if we could survive without allocation. |
| 4456 __ cmp(eax, ecx); |
| 4457 |
| 4458 if (IsFastSmiOrObjectElementsKind(elements_kind())) { |
| 4459 __ j(greater, &attempt_to_grow_elements); |
| 4460 |
| 4461 // Check if value is a smi. |
| 4462 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
| 4463 __ JumpIfNotSmi(ecx, &with_write_barrier); |
| 4464 |
| 4465 // Store the value. |
| 4466 __ mov(FieldOperand(edi, eax, times_half_pointer_size, |
| 4467 FixedArray::kHeaderSize - argc * kPointerSize), |
| 4468 ecx); |
| 4469 } else { |
| 4470 __ j(greater, &call_builtin); |
| 4471 |
| 4472 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
| 4473 __ StoreNumberToDoubleElements( |
| 4474 ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize); |
| 4475 } |
| 4476 |
| 4477 // Save new length. |
| 4478 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
| 4479 __ ret((argc + 1) * kPointerSize); |
| 4480 |
| 4481 if (IsFastDoubleElementsKind(elements_kind())) { |
| 4482 __ bind(&call_builtin); |
| 4483 __ TailCallExternalReference( |
| 4484 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4485 return; |
| 4486 } |
| 4487 |
| 4488 __ bind(&with_write_barrier); |
| 4489 |
| 4490 if (IsFastSmiElementsKind(elements_kind())) { |
| 4491 if (FLAG_trace_elements_transitions) __ jmp(&call_builtin); |
| 4492 |
| 4493 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
| 4494 isolate->factory()->heap_number_map()); |
| 4495 __ j(equal, &call_builtin); |
| 4496 |
| 4497 ElementsKind target_kind = IsHoleyElementsKind(elements_kind()) |
| 4498 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; |
| 4499 __ mov(ebx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX)); |
| 4500 __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset)); |
| 4501 __ mov(ebx, ContextOperand(ebx, Context::JS_ARRAY_MAPS_INDEX)); |
| 4502 const int header_size = FixedArrayBase::kHeaderSize; |
| 4503 // Verify that the object can be transitioned in place. |
| 4504 const int origin_offset = header_size + elements_kind() * kPointerSize; |
| 4505 __ mov(edi, FieldOperand(ebx, origin_offset)); |
| 4506 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 4507 __ j(not_equal, &call_builtin); |
| 4508 |
| 4509 const int target_offset = header_size + target_kind * kPointerSize; |
| 4510 __ mov(ebx, FieldOperand(ebx, target_offset)); |
| 4511 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 4512 masm, DONT_TRACK_ALLOCATION_SITE, NULL); |
| 4513 // Restore edi used as a scratch register for the write barrier used while |
| 4514 // setting the map. |
| 4515 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); |
| 4516 } |
| 4517 |
| 4518 // Save new length. |
| 4519 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
| 4520 |
| 4521 // Store the value. |
| 4522 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size, |
| 4523 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 4524 __ mov(Operand(edx, 0), ecx); |
| 4525 |
| 4526 __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 4527 OMIT_SMI_CHECK); |
| 4528 |
| 4529 __ ret((argc + 1) * kPointerSize); |
| 4530 |
| 4531 __ bind(&attempt_to_grow_elements); |
| 4532 if (!FLAG_inline_new) { |
| 4533 __ bind(&call_builtin); |
| 4534 __ TailCallExternalReference( |
| 4535 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4536 return; |
| 4537 } |
| 4538 |
| 4539 __ mov(ebx, Operand(esp, argc * kPointerSize)); |
| 4540 // Growing elements that are SMI-only requires special handling in case the |
| 4541 // new element is non-Smi. For now, delegate to the builtin. |
| 4542 if (IsFastSmiElementsKind(elements_kind())) { |
| 4543 __ JumpIfNotSmi(ebx, &call_builtin); |
| 4544 } |
| 4545 |
| 4546 // We could be lucky and the elements array could be at the top of new-space. |
| 4547 // In this case we can just grow it in place by moving the allocation pointer |
| 4548 // up. |
| 4549 ExternalReference new_space_allocation_top = |
| 4550 ExternalReference::new_space_allocation_top_address(isolate); |
| 4551 ExternalReference new_space_allocation_limit = |
| 4552 ExternalReference::new_space_allocation_limit_address(isolate); |
| 4553 |
| 4554 const int kAllocationDelta = 4; |
| 4555 ASSERT(kAllocationDelta >= argc); |
| 4556 // Load top. |
| 4557 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); |
| 4558 |
| 4559 // Check if it's the end of elements. |
| 4560 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size, |
| 4561 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 4562 __ cmp(edx, ecx); |
| 4563 __ j(not_equal, &call_builtin); |
| 4564 __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); |
| 4565 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); |
| 4566 __ j(above, &call_builtin); |
| 4567 |
| 4568 // We fit and could grow elements. |
| 4569 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); |
| 4570 |
| 4571 // Push the argument... |
| 4572 __ mov(Operand(edx, 0), ebx); |
| 4573 // ... and fill the rest with holes. |
| 4574 for (int i = 1; i < kAllocationDelta; i++) { |
| 4575 __ mov(Operand(edx, i * kPointerSize), |
| 4576 isolate->factory()->the_hole_value()); |
| 4577 } |
| 4578 |
| 4579 if (IsFastObjectElementsKind(elements_kind())) { |
| 4580 // We know the elements array is in new space so we don't need the |
| 4581 // remembered set, but we just pushed a value onto it so we may have to tell |
| 4582 // the incremental marker to rescan the object that we just grew. We don't |
| 4583 // need to worry about the holes because they are in old space and already |
| 4584 // marked black. |
| 4585 __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |
| 4586 } |
| 4587 |
| 4588 // Restore receiver to edx as finish sequence assumes it's here. |
| 4589 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 4590 |
| 4591 // Increment element's and array's sizes. |
| 4592 __ add(FieldOperand(edi, FixedArray::kLengthOffset), |
| 4593 Immediate(Smi::FromInt(kAllocationDelta))); |
| 4594 |
| 4595 // NOTE: This only happen in new-space, where we don't care about the |
| 4596 // black-byte-count on pages. Otherwise we should update that too if the |
| 4597 // object is black. |
| 4598 |
| 4599 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
| 4600 __ ret((argc + 1) * kPointerSize); |
| 4601 |
| 4602 __ bind(&call_builtin); |
| 4603 __ TailCallExternalReference( |
| 4604 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |
| 4605 } |
| 4606 |
| 4607 |
4416 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 4608 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
4417 // ----------- S t a t e ------------- | 4609 // ----------- S t a t e ------------- |
4418 // -- edx : left | 4610 // -- edx : left |
4419 // -- eax : right | 4611 // -- eax : right |
4420 // -- esp[0] : return address | 4612 // -- esp[0] : return address |
4421 // ----------------------------------- | 4613 // ----------------------------------- |
4422 Isolate* isolate = masm->isolate(); | 4614 Isolate* isolate = masm->isolate(); |
4423 | 4615 |
4424 // Load ecx with the allocation site. We stick an undefined dummy value here | 4616 // Load ecx with the allocation site. We stick an undefined dummy value here |
4425 // and replace it with the real allocation site later when we instantiate this | 4617 // and replace it with the real allocation site later when we instantiate this |
(...skipping 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5719 __ bind(&fast_elements_case); | 5911 __ bind(&fast_elements_case); |
5720 GenerateCase(masm, FAST_ELEMENTS); | 5912 GenerateCase(masm, FAST_ELEMENTS); |
5721 } | 5913 } |
5722 | 5914 |
5723 | 5915 |
5724 #undef __ | 5916 #undef __ |
5725 | 5917 |
5726 } } // namespace v8::internal | 5918 } } // namespace v8::internal |
5727 | 5919 |
5728 #endif // V8_TARGET_ARCH_IA32 | 5920 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |