OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 4302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4313 // If so, jump to the deferred code passing the literals array. | 4313 // If so, jump to the deferred code passing the literals array. |
4314 DeferredArrayLiteral* deferred = | 4314 DeferredArrayLiteral* deferred = |
4315 new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node); | 4315 new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node); |
4316 __ cmp(boilerplate.reg(), Factory::undefined_value()); | 4316 __ cmp(boilerplate.reg(), Factory::undefined_value()); |
4317 deferred->Branch(equal); | 4317 deferred->Branch(equal); |
4318 deferred->BindExit(); | 4318 deferred->BindExit(); |
4319 literals.Unuse(); | 4319 literals.Unuse(); |
4320 | 4320 |
4321 // Push the resulting array literal boilerplate on the stack. | 4321 // Push the resulting array literal boilerplate on the stack. |
4322 frame_->Push(&boilerplate); | 4322 frame_->Push(&boilerplate); |
| 4323 |
4323 // Clone the boilerplate object. | 4324 // Clone the boilerplate object. |
4324 Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate; | 4325 int length = node->values()->length(); |
4325 if (node->depth() == 1) { | 4326 Result clone; |
4326 clone_function_id = Runtime::kCloneShallowLiteralBoilerplate; | 4327 if (node->depth() == 1 && |
| 4328 length <= FastCloneShallowArrayStub::kMaximumLength) { |
| 4329 FastCloneShallowArrayStub stub(length); |
| 4330 clone = frame_->CallStub(&stub, 1); |
| 4331 } else { |
| 4332 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); |
4327 } | 4333 } |
4328 Result clone = frame_->CallRuntime(clone_function_id, 1); | |
4329 // Push the newly cloned literal object as the result. | 4334 // Push the newly cloned literal object as the result. |
4330 frame_->Push(&clone); | 4335 frame_->Push(&clone); |
4331 | 4336 |
4332 // Generate code to set the elements in the array that are not | 4337 // Generate code to set the elements in the array that are not |
4333 // literals. | 4338 // literals. |
4334 for (int i = 0; i < node->values()->length(); i++) { | 4339 for (int i = 0; i < length; i++) { |
4335 Expression* value = node->values()->at(i); | 4340 Expression* value = node->values()->at(i); |
4336 | 4341 |
4337 // If value is a literal the property value is already set in the | 4342 // If value is a literal the property value is already set in the |
4338 // boilerplate object. | 4343 // boilerplate object. |
4339 if (value->AsLiteral() != NULL) continue; | 4344 if (value->AsLiteral() != NULL) continue; |
4340 // If value is a materialized literal the property value is already set | 4345 // If value is a materialized literal the property value is already set |
4341 // in the boilerplate object if it is simple. | 4346 // in the boilerplate object if it is simple. |
4342 if (CompileTimeValue::IsCompileTimeValue(value)) continue; | 4347 if (CompileTimeValue::IsCompileTimeValue(value)) continue; |
4343 | 4348 |
4344 // The property must be set by generated code. | 4349 // The property must be set by generated code. |
(...skipping 2285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6630 // Return and remove the on-stack parameter. | 6635 // Return and remove the on-stack parameter. |
6631 __ mov(esi, Operand(eax)); | 6636 __ mov(esi, Operand(eax)); |
6632 __ ret(1 * kPointerSize); | 6637 __ ret(1 * kPointerSize); |
6633 | 6638 |
6634 // Need to collect. Call into runtime system. | 6639 // Need to collect. Call into runtime system. |
6635 __ bind(&gc); | 6640 __ bind(&gc); |
6636 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); | 6641 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); |
6637 } | 6642 } |
6638 | 6643 |
6639 | 6644 |
| 6645 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { |
| 6646 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; |
| 6647 int size = JSArray::kSize + elements_size; |
| 6648 |
| 6649 // Allocate both the JS array and the elements array in one big |
| 6650 // allocation. This avoid multiple limit checks. |
| 6651 Label gc; |
| 6652 __ AllocateInNewSpace(size, eax, ebx, ecx, &gc, TAG_OBJECT); |
| 6653 |
| 6654 // Get the boilerplate from the stack. |
| 6655 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 6656 |
| 6657 // Copy the JS array part. |
| 6658 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 6659 if ((i != JSArray::kElementsOffset) || (length_ == 0)) { |
| 6660 __ mov(ebx, FieldOperand(ecx, i)); |
| 6661 __ mov(FieldOperand(eax, i), ebx); |
| 6662 } |
| 6663 } |
| 6664 |
| 6665 if (length_ > 0) { |
| 6666 // Get hold of the elements array of the boilerplate and setup the |
| 6667 // elements pointer in the resulting object. |
| 6668 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset)); |
| 6669 __ lea(edx, Operand(eax, JSArray::kSize)); |
| 6670 __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx); |
| 6671 |
| 6672 // Copy the elements array. |
| 6673 for (int i = 0; i < elements_size; i += kPointerSize) { |
| 6674 __ mov(ebx, FieldOperand(ecx, i)); |
| 6675 __ mov(FieldOperand(edx, i), ebx); |
| 6676 } |
| 6677 } |
| 6678 |
| 6679 // Return and remove the on-stack parameter. |
| 6680 __ ret(1 * kPointerSize); |
| 6681 |
| 6682 __ bind(&gc); |
| 6683 ExternalReference runtime(Runtime::kCloneShallowLiteralBoilerplate); |
| 6684 __ TailCallRuntime(runtime, 1, 1); |
| 6685 } |
| 6686 |
| 6687 |
6640 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 6688 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
6641 void ToBooleanStub::Generate(MacroAssembler* masm) { | 6689 void ToBooleanStub::Generate(MacroAssembler* masm) { |
6642 Label false_result, true_result, not_string; | 6690 Label false_result, true_result, not_string; |
6643 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 6691 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
6644 | 6692 |
6645 // 'null' => false. | 6693 // 'null' => false. |
6646 __ cmp(eax, Factory::null_value()); | 6694 __ cmp(eax, Factory::null_value()); |
6647 __ j(equal, &false_result); | 6695 __ j(equal, &false_result); |
6648 | 6696 |
6649 // Get the map and type of the heap object. | 6697 // Get the map and type of the heap object. |
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7542 } | 7590 } |
7543 | 7591 |
7544 | 7592 |
7545 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { | 7593 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { |
7546 // The displacement is used for skipping the return address and the | 7594 // The displacement is used for skipping the return address and the |
7547 // frame pointer on the stack. It is the offset of the last | 7595 // frame pointer on the stack. It is the offset of the last |
7548 // parameter (if any) relative to the frame pointer. | 7596 // parameter (if any) relative to the frame pointer. |
7549 static const int kDisplacement = 2 * kPointerSize; | 7597 static const int kDisplacement = 2 * kPointerSize; |
7550 | 7598 |
7551 // Check if the calling frame is an arguments adaptor frame. | 7599 // Check if the calling frame is an arguments adaptor frame. |
7552 Label runtime; | 7600 Label adaptor_frame, try_allocate, runtime; |
7553 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 7601 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
7554 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 7602 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
7555 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 7603 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
7556 __ j(not_equal, &runtime); | 7604 __ j(equal, &adaptor_frame); |
| 7605 |
| 7606 // Get the length from the frame. |
| 7607 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 7608 __ jmp(&try_allocate); |
7557 | 7609 |
7558 // Patch the arguments.length and the parameters pointer. | 7610 // Patch the arguments.length and the parameters pointer. |
| 7611 __ bind(&adaptor_frame); |
7559 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 7612 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
7560 __ mov(Operand(esp, 1 * kPointerSize), ecx); | 7613 __ mov(Operand(esp, 1 * kPointerSize), ecx); |
7561 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); | 7614 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); |
7562 __ mov(Operand(esp, 2 * kPointerSize), edx); | 7615 __ mov(Operand(esp, 2 * kPointerSize), edx); |
7563 | 7616 |
| 7617 // Try the new space allocation. Start out with computing the size of |
| 7618 // the arguments object and the elements array. |
| 7619 Label add_arguments_object; |
| 7620 __ bind(&try_allocate); |
| 7621 __ test(ecx, Operand(ecx)); |
| 7622 __ j(zero, &add_arguments_object); |
| 7623 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); |
| 7624 __ bind(&add_arguments_object); |
| 7625 __ add(Operand(ecx), Immediate(Heap::kArgumentsObjectSize)); |
| 7626 |
| 7627 // Do the allocation of both objects in one go. |
| 7628 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); |
| 7629 |
| 7630 // Get the arguments boilerplate from the current (global) context. |
| 7631 int offset = Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX); |
| 7632 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 7633 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); |
| 7634 __ mov(edi, Operand(edi, offset)); |
| 7635 |
| 7636 // Copy the JS object part. |
| 7637 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| 7638 __ mov(ebx, FieldOperand(edi, i)); |
| 7639 __ mov(FieldOperand(eax, i), ebx); |
| 7640 } |
| 7641 |
| 7642 // Setup the callee in-object property. |
| 7643 ASSERT(Heap::arguments_callee_index == 0); |
| 7644 __ mov(ebx, Operand(esp, 3 * kPointerSize)); |
| 7645 __ mov(FieldOperand(eax, JSObject::kHeaderSize), ebx); |
| 7646 |
| 7647 // Get the length (smi tagged) and set that as an in-object property too. |
| 7648 ASSERT(Heap::arguments_length_index == 1); |
| 7649 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 7650 __ mov(FieldOperand(eax, JSObject::kHeaderSize + kPointerSize), ecx); |
| 7651 |
| 7652 // If there are no actual arguments, we're done. |
| 7653 Label done; |
| 7654 __ test(ecx, Operand(ecx)); |
| 7655 __ j(zero, &done); |
| 7656 |
| 7657 // Get the parameters pointer from the stack and untag the length. |
| 7658 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 7659 __ sar(ecx, kSmiTagSize); |
| 7660 |
| 7661 // Setup the elements pointer in the allocated arguments object and |
| 7662 // initialize the header in the elements fixed array. |
| 7663 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize)); |
| 7664 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
| 7665 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 7666 Immediate(Factory::fixed_array_map())); |
| 7667 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
| 7668 |
| 7669 // Copy the fixed array slots. |
| 7670 Label loop; |
| 7671 __ bind(&loop); |
| 7672 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. |
| 7673 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); |
| 7674 __ add(Operand(edi), Immediate(kPointerSize)); |
| 7675 __ sub(Operand(edx), Immediate(kPointerSize)); |
| 7676 __ dec(ecx); |
| 7677 __ test(ecx, Operand(ecx)); |
| 7678 __ j(not_zero, &loop); |
| 7679 |
| 7680 // Return and remove the on-stack parameters. |
| 7681 __ bind(&done); |
| 7682 __ ret(3 * kPointerSize); |
| 7683 |
7564 // Do the runtime call to allocate the arguments object. | 7684 // Do the runtime call to allocate the arguments object. |
7565 __ bind(&runtime); | 7685 __ bind(&runtime); |
7566 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); | 7686 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); |
7567 } | 7687 } |
7568 | 7688 |
7569 | 7689 |
7570 void CompareStub::Generate(MacroAssembler* masm) { | 7690 void CompareStub::Generate(MacroAssembler* masm) { |
7571 Label call_builtin, done; | 7691 Label call_builtin, done; |
7572 | 7692 |
7573 // NOTICE! This code is only reached after a smi-fast-case check, so | 7693 // NOTICE! This code is only reached after a smi-fast-case check, so |
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8558 __ add(Operand(dest), Immediate(2)); | 8678 __ add(Operand(dest), Immediate(2)); |
8559 } | 8679 } |
8560 __ sub(Operand(count), Immediate(1)); | 8680 __ sub(Operand(count), Immediate(1)); |
8561 __ j(not_zero, &loop); | 8681 __ j(not_zero, &loop); |
8562 } | 8682 } |
8563 | 8683 |
8564 | 8684 |
8565 #undef __ | 8685 #undef __ |
8566 | 8686 |
8567 } } // namespace v8::internal | 8687 } } // namespace v8::internal |
OLD | NEW |