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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 3144002: Copy-on-write arrays. (Closed)
Patch Set: Review fixes. Created 10 years, 4 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
« no previous file with comments | « src/heap.cc ('k') | src/ia32/full-codegen-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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 5692 matching lines...) Expand 10 before | Expand all | Expand 10 after
5703 5703
5704 // Load the literals array of the function. 5704 // Load the literals array of the function.
5705 __ mov(literals.reg(), 5705 __ mov(literals.reg(),
5706 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); 5706 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
5707 5707
5708 frame_->Push(&literals); 5708 frame_->Push(&literals);
5709 frame_->Push(Smi::FromInt(node->literal_index())); 5709 frame_->Push(Smi::FromInt(node->literal_index()));
5710 frame_->Push(node->constant_elements()); 5710 frame_->Push(node->constant_elements());
5711 int length = node->values()->length(); 5711 int length = node->values()->length();
5712 Result clone; 5712 Result clone;
5713 if (node->depth() > 1) { 5713 if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
5714 FastCloneShallowArrayStub stub(
5715 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
5716 clone = frame_->CallStub(&stub, 3);
5717 } else if (node->depth() > 1) {
5714 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); 5718 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
5715 } else if (length > FastCloneShallowArrayStub::kMaximumLength) { 5719 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
5716 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 5720 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
5717 } else { 5721 } else {
5718 FastCloneShallowArrayStub stub(length); 5722 FastCloneShallowArrayStub stub(
5723 FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
5719 clone = frame_->CallStub(&stub, 3); 5724 clone = frame_->CallStub(&stub, 3);
5720 } 5725 }
5721 frame_->Push(&clone); 5726 frame_->Push(&clone);
5722 5727
5723 // Generate code to set the elements in the array that are not 5728 // Generate code to set the elements in the array that are not
5724 // literals. 5729 // literals.
5725 for (int i = 0; i < length; i++) { 5730 for (int i = 0; i < length; i++) {
5726 Expression* value = node->values()->at(i); 5731 Expression* value = node->values()->at(i);
5727 5732
5728 // If value is a literal the property value is already set in the 5733 if (!CompileTimeValue::ArrayLiteralElementNeedsInitialization(value)) {
5729 // boilerplate object. 5734 continue;
5730 if (value->AsLiteral() != NULL) continue; 5735 }
5731 // If value is a materialized literal the property value is already set
5732 // in the boilerplate object if it is simple.
5733 if (CompileTimeValue::IsCompileTimeValue(value)) continue;
5734 5736
5735 // The property must be set by generated code. 5737 // The property must be set by generated code.
5736 Load(value); 5738 Load(value);
5737 5739
5738 // Get the property value off the stack. 5740 // Get the property value off the stack.
5739 Result prop_value = frame_->Pop(); 5741 Result prop_value = frame_->Pop();
5740 prop_value.ToRegister(); 5742 prop_value.ToRegister();
5741 5743
5742 // Fetch the array literal while leaving a copy on the stack and 5744 // Fetch the array literal while leaving a copy on the stack and
5743 // use it to get the elements array. 5745 // use it to get the elements array.
(...skipping 1848 matching lines...) Expand 10 before | Expand all | Expand 10 after
7592 7594
7593 // Fetch the map and check if array is in fast case. 7595 // Fetch the map and check if array is in fast case.
7594 // Check that object doesn't require security checks and 7596 // Check that object doesn't require security checks and
7595 // has no indexed interceptor. 7597 // has no indexed interceptor.
7596 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg()); 7598 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
7597 deferred->Branch(below); 7599 deferred->Branch(below);
7598 __ test_b(FieldOperand(tmp1.reg(), Map::kBitFieldOffset), 7600 __ test_b(FieldOperand(tmp1.reg(), Map::kBitFieldOffset),
7599 KeyedLoadIC::kSlowCaseBitFieldMask); 7601 KeyedLoadIC::kSlowCaseBitFieldMask);
7600 deferred->Branch(not_zero); 7602 deferred->Branch(not_zero);
7601 7603
7602 // Check the object's elements are in fast case. 7604 // Check the object's elements are in fast case and writable.
7603 __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset)); 7605 __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
7604 __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset), 7606 __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
7605 Immediate(Factory::fixed_array_map())); 7607 Immediate(Factory::fixed_array_map()));
7606 deferred->Branch(not_equal); 7608 deferred->Branch(not_equal);
7607 7609
7608 // Smi-tagging is equivalent to multiplying by 2. 7610 // Smi-tagging is equivalent to multiplying by 2.
7609 STATIC_ASSERT(kSmiTag == 0); 7611 STATIC_ASSERT(kSmiTag == 0);
7610 STATIC_ASSERT(kSmiTagSize == 1); 7612 STATIC_ASSERT(kSmiTagSize == 1);
7611 7613
7612 // Check that both indices are smis. 7614 // Check that both indices are smis.
(...skipping 1874 matching lines...) Expand 10 before | Expand all | Expand 10 after
9487 deferred->Branch(not_equal); 9489 deferred->Branch(not_equal);
9488 9490
9489 // Check that the key is a smi. 9491 // Check that the key is a smi.
9490 if (!key.is_smi()) { 9492 if (!key.is_smi()) {
9491 __ test(key.reg(), Immediate(kSmiTagMask)); 9493 __ test(key.reg(), Immediate(kSmiTagMask));
9492 deferred->Branch(not_zero); 9494 deferred->Branch(not_zero);
9493 } else { 9495 } else {
9494 if (FLAG_debug_code) __ AbortIfNotSmi(key.reg()); 9496 if (FLAG_debug_code) __ AbortIfNotSmi(key.reg());
9495 } 9497 }
9496 9498
9497 // Get the elements array from the receiver and check that it 9499 // Get the elements array from the receiver.
9498 // is not a dictionary.
9499 __ mov(elements.reg(), 9500 __ mov(elements.reg(),
9500 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); 9501 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
9501 if (FLAG_debug_code) { 9502 __ AssertFastElements(elements.reg());
9502 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
9503 Immediate(Factory::fixed_array_map()));
9504 __ Assert(equal, "JSObject with fast elements map has slow elements");
9505 }
9506 9503
9507 // Check that the key is within bounds. 9504 // Check that the key is within bounds.
9508 __ cmp(key.reg(), 9505 __ cmp(key.reg(),
9509 FieldOperand(elements.reg(), FixedArray::kLengthOffset)); 9506 FieldOperand(elements.reg(), FixedArray::kLengthOffset));
9510 deferred->Branch(above_equal); 9507 deferred->Branch(above_equal);
9511 9508
9512 // Load and check that the result is not the hole. 9509 // Load and check that the result is not the hole.
9513 // Key holds a smi. 9510 // Key holds a smi.
9514 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 9511 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
9515 __ mov(elements.reg(), 9512 __ mov(elements.reg(),
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
9892 Label slow_case; 9889 Label slow_case;
9893 __ mov(ecx, Operand(esp, 3 * kPointerSize)); 9890 __ mov(ecx, Operand(esp, 3 * kPointerSize));
9894 __ mov(eax, Operand(esp, 2 * kPointerSize)); 9891 __ mov(eax, Operand(esp, 2 * kPointerSize));
9895 STATIC_ASSERT(kPointerSize == 4); 9892 STATIC_ASSERT(kPointerSize == 4);
9896 STATIC_ASSERT(kSmiTagSize == 1); 9893 STATIC_ASSERT(kSmiTagSize == 1);
9897 STATIC_ASSERT(kSmiTag == 0); 9894 STATIC_ASSERT(kSmiTag == 0);
9898 __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax)); 9895 __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax));
9899 __ cmp(ecx, Factory::undefined_value()); 9896 __ cmp(ecx, Factory::undefined_value());
9900 __ j(equal, &slow_case); 9897 __ j(equal, &slow_case);
9901 9898
9899 if (FLAG_debug_code) {
9900 const char* message;
9901 Handle<Map> expected_map;
9902 if (mode_ == CLONE_ELEMENTS) {
9903 message = "Expected (writable) fixed array";
9904 expected_map = Factory::fixed_array_map();
9905 } else {
9906 ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS);
9907 message = "Expected copy-on-write fixed array";
9908 expected_map = Factory::fixed_cow_array_map();
9909 }
9910 __ push(ecx);
9911 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
9912 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), expected_map);
9913 __ Assert(equal, message);
9914 __ pop(ecx);
9915 }
9916
9902 // Allocate both the JS array and the elements array in one big 9917 // Allocate both the JS array and the elements array in one big
9903 // allocation. This avoids multiple limit checks. 9918 // allocation. This avoids multiple limit checks.
9904 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT); 9919 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT);
9905 9920
9906 // Copy the JS array part. 9921 // Copy the JS array part.
9907 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 9922 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
9908 if ((i != JSArray::kElementsOffset) || (length_ == 0)) { 9923 if ((i != JSArray::kElementsOffset) || (length_ == 0)) {
9909 __ mov(ebx, FieldOperand(ecx, i)); 9924 __ mov(ebx, FieldOperand(ecx, i));
9910 __ mov(FieldOperand(eax, i), ebx); 9925 __ mov(FieldOperand(eax, i), ebx);
9911 } 9926 }
9912 } 9927 }
9913 9928
9914 if (length_ > 0) { 9929 if (length_ > 0) {
9915 // Get hold of the elements array of the boilerplate and setup the 9930 // Get hold of the elements array of the boilerplate and setup the
9916 // elements pointer in the resulting object. 9931 // elements pointer in the resulting object.
9917 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset)); 9932 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
9918 __ lea(edx, Operand(eax, JSArray::kSize)); 9933 __ lea(edx, Operand(eax, JSArray::kSize));
9919 __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx); 9934 __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx);
9920 9935
9921 // Copy the elements array. 9936 // Copy the elements array.
9922 for (int i = 0; i < elements_size; i += kPointerSize) { 9937 for (int i = 0; i < elements_size; i += kPointerSize) {
9923 __ mov(ebx, FieldOperand(ecx, i)); 9938 __ mov(ebx, FieldOperand(ecx, i));
9924 __ mov(FieldOperand(edx, i), ebx); 9939 __ mov(FieldOperand(edx, i), ebx);
9925 } 9940 }
9926 } 9941 }
9927 9942
9943 if (mode_ == COPY_ON_WRITE_ELEMENTS) {
9944 __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
9945 }
9946
9928 // Return and remove the on-stack parameters. 9947 // Return and remove the on-stack parameters.
9929 __ ret(3 * kPointerSize); 9948 __ ret(3 * kPointerSize);
9930 9949
9931 __ bind(&slow_case); 9950 __ bind(&slow_case);
9932 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 9951 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
9933 } 9952 }
9934 9953
9935 9954
9936 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 9955 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
9937 void ToBooleanStub::Generate(MacroAssembler* masm) { 9956 void ToBooleanStub::Generate(MacroAssembler* masm) {
(...skipping 4450 matching lines...) Expand 10 before | Expand all | Expand 10 after
14388 masm.GetCode(&desc); 14407 masm.GetCode(&desc);
14389 // Call the function from C++. 14408 // Call the function from C++.
14390 return FUNCTION_CAST<MemCopyFunction>(buffer); 14409 return FUNCTION_CAST<MemCopyFunction>(buffer);
14391 } 14410 }
14392 14411
14393 #undef __ 14412 #undef __
14394 14413
14395 } } // namespace v8::internal 14414 } } // namespace v8::internal
14396 14415
14397 #endif // V8_TARGET_ARCH_IA32 14416 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/heap.cc ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698