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); | |
mvstanton
2014/01/20 14:49:13
Could you write the !FLAG_inline_new case here, su
| |
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 int offset = FixedArrayBase::kHeaderSize + target_kind * kPointerSize; | |
4503 __ mov(ebx, FieldOperand(ebx, offset)); | |
4504 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | |
4505 masm, DONT_TRACK_ALLOCATION_SITE, NULL); | |
mvstanton
2014/01/20 14:49:13
Do we know that the array passed in is from the cu
Toon Verwaest
2014/01/20 16:14:38
Good catch. We currently don't.
On 2014/01/20 14:
| |
4506 // Restore edi used as a scratch register for the write barrier used while | |
4507 // setting the map. | |
4508 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); | |
4509 } | |
4510 | |
4511 // Save new length. | |
4512 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | |
4513 | |
4514 // Store the value. | |
4515 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size, | |
4516 FixedArray::kHeaderSize - argc * kPointerSize)); | |
4517 __ mov(Operand(edx, 0), ecx); | |
4518 | |
4519 __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
4520 OMIT_SMI_CHECK); | |
4521 | |
4522 __ ret((argc + 1) * kPointerSize); | |
4523 | |
4524 __ bind(&attempt_to_grow_elements); | |
4525 if (!FLAG_inline_new) { | |
4526 __ TailCallExternalReference( | |
4527 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
4528 return; | |
4529 } | |
4530 | |
4531 __ mov(ebx, Operand(esp, argc * kPointerSize)); | |
4532 // Growing elements that are SMI-only requires special handling in case the | |
4533 // new element is non-Smi. For now, delegate to the builtin. | |
4534 if (IsFastSmiElementsKind(elements_kind())) { | |
4535 __ JumpIfNotSmi(ebx, &call_builtin); | |
4536 } | |
4537 | |
4538 // We could be lucky and the elements array could be at the top of new-space. | |
4539 // In this case we can just grow it in place by moving the allocation pointer | |
4540 // up. | |
4541 ExternalReference new_space_allocation_top = | |
4542 ExternalReference::new_space_allocation_top_address(isolate); | |
4543 ExternalReference new_space_allocation_limit = | |
4544 ExternalReference::new_space_allocation_limit_address(isolate); | |
4545 | |
4546 const int kAllocationDelta = 4; | |
mvstanton
2014/01/20 14:49:13
ASSERT(kAllocationDelta >= argc);
Toon Verwaest
2014/01/20 16:14:38
Done.
| |
4547 // Load top. | |
4548 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); | |
4549 | |
4550 // Check if it's the end of elements. | |
4551 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size, | |
4552 FixedArray::kHeaderSize - argc * kPointerSize)); | |
4553 __ cmp(edx, ecx); | |
4554 __ j(not_equal, &call_builtin); | |
4555 __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); | |
4556 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); | |
4557 __ j(above, &call_builtin); | |
4558 | |
4559 // We fit and could grow elements. | |
4560 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); | |
4561 | |
4562 // Push the argument... | |
4563 __ mov(Operand(edx, 0), ebx); | |
4564 // ... and fill the rest with holes. | |
4565 for (int i = 1; i < kAllocationDelta; i++) { | |
4566 __ mov(Operand(edx, i * kPointerSize), | |
4567 isolate->factory()->the_hole_value()); | |
4568 } | |
4569 | |
4570 if (IsFastObjectElementsKind(elements_kind())) { | |
4571 // We know the elements array is in new space so we don't need the | |
mvstanton
2014/01/20 14:49:13
How do we know the elements array is in new space?
Toon Verwaest
2014/01/20 16:14:38
Line 4541 (etc.) checks that. It would have gone t
| |
4572 // remembered set, but we just pushed a value onto it so we may have to tell | |
4573 // the incremental marker to rescan the object that we just grew. We don't | |
4574 // need to worry about the holes because they are in old space and already | |
4575 // marked black. | |
4576 __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); | |
4577 } | |
4578 | |
4579 // Restore receiver to edx as finish sequence assumes it's here. | |
4580 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
4581 | |
4582 // Increment element's and array's sizes. | |
4583 __ add(FieldOperand(edi, FixedArray::kLengthOffset), | |
4584 Immediate(Smi::FromInt(kAllocationDelta))); | |
4585 | |
4586 // NOTE: This only happen in new-space, where we don't care about the | |
4587 // black-byte-count on pages. Otherwise we should update that too if the | |
4588 // object is black. | |
4589 | |
4590 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | |
4591 __ ret((argc + 1) * kPointerSize); | |
4592 | |
4593 __ bind(&call_builtin); | |
4594 __ TailCallExternalReference( | |
4595 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
4596 } | |
4597 | |
4598 | |
4416 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 4599 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
4417 // ----------- S t a t e ------------- | 4600 // ----------- S t a t e ------------- |
4418 // -- edx : left | 4601 // -- edx : left |
4419 // -- eax : right | 4602 // -- eax : right |
4420 // -- esp[0] : return address | 4603 // -- esp[0] : return address |
4421 // ----------------------------------- | 4604 // ----------------------------------- |
4422 Isolate* isolate = masm->isolate(); | 4605 Isolate* isolate = masm->isolate(); |
4423 | 4606 |
4424 // Load ecx with the allocation site. We stick an undefined dummy value here | 4607 // 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 | 4608 // 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); | 5902 __ bind(&fast_elements_case); |
5720 GenerateCase(masm, FAST_ELEMENTS); | 5903 GenerateCase(masm, FAST_ELEMENTS); |
5721 } | 5904 } |
5722 | 5905 |
5723 | 5906 |
5724 #undef __ | 5907 #undef __ |
5725 | 5908 |
5726 } } // namespace v8::internal | 5909 } } // namespace v8::internal |
5727 | 5910 |
5728 #endif // V8_TARGET_ARCH_IA32 | 5911 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |