Chromium Code Reviews| 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 |