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

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: 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);
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
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
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