Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 143213003: Turn ArrayPush into a stub specialized on the elements kind and argc. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Properly bind label Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/code-stubs.h ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698