📄 builtins-ia32.cc.svn-base
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "codegen-inl.h"#include "debug.h"#include "runtime.h"namespace v8 { namespace internal {#define __ masm->void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) { // TODO(1238487): Don't pass the function in a static variable. ExternalReference passed = ExternalReference::builtin_passed_function(); __ mov(Operand::StaticVariable(passed), edi); // The actual argument count has already been loaded into register // eax, but JumpToBuiltin expects eax to contain the number of // arguments including the receiver. __ inc(eax); __ JumpToBuiltin(ExternalReference(id));}void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax: number of arguments // -- edi: constructor function // ----------------------------------- // Enter an internal frame. __ EnterInternalFrame(); // Store a smi-tagged arguments count on the stack. __ shl(eax, kSmiTagSize); __ push(eax); // Push the function to invoke on the stack. __ push(edi); // Try to allocate the object without transitioning into C code. If any of the // preconditions is not met, the code bails out to the runtime call. Label rt_call, allocated; if (FLAG_inline_new) { Label undo_allocation; ExternalReference debug_step_in_fp = ExternalReference::debug_step_in_fp_address(); __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); __ j(not_equal, &rt_call); // Check that function is not a Smi. __ test(edi, Immediate(kSmiTagMask)); __ j(zero, &rt_call); // Check that function is a JSFunction __ mov(eax, FieldOperand(edi, JSFunction::kMapOffset)); __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); __ cmp(eax, JS_FUNCTION_TYPE); __ j(not_equal, &rt_call); // Verified that the constructor is a JSFunction. // Load the initial map and verify that it is in fact a map. // edi: constructor __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); // Will both indicate a NULL and a Smi __ test(eax, Immediate(kSmiTagMask)); __ j(zero, &rt_call); // edi: constructor // eax: initial map (if proven valid below) __ mov(ebx, FieldOperand(eax, JSFunction::kMapOffset)); __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ cmp(ebx, MAP_TYPE); __ j(not_equal, &rt_call); // Check that the constructor is not constructing a JSFunction (see comments // in Runtime_NewObject in runtime.cc). In which case the initial map's // instance type would be JS_FUNCTION_TYPE. // edi: constructor // eax: initial map __ movzx_b(ebx, FieldOperand(eax, Map::kInstanceTypeOffset)); __ cmp(ebx, JS_FUNCTION_TYPE); __ j(equal, &rt_call); // Now allocate the JSObject on the heap. // edi: constructor // eax: initial map __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); // Make sure that the maximum heap object size will never cause us // problem here, because it is always greater than the maximum // instance size that can be represented in a byte. ASSERT(Heap::MaxHeapObjectSize() >= (1 << kBitsPerByte)); ExternalReference new_space_allocation_top = ExternalReference::new_space_allocation_top_address(); __ mov(ebx, Operand::StaticVariable(new_space_allocation_top)); __ add(edi, Operand(ebx)); // Calculate new top ExternalReference new_space_allocation_limit = ExternalReference::new_space_allocation_limit_address(); __ cmp(edi, Operand::StaticVariable(new_space_allocation_limit)); __ j(greater_equal, &rt_call); // Allocated the JSObject, now initialize the fields. // eax: initial map // ebx: JSObject // edi: start of next object __ mov(Operand(ebx, JSObject::kMapOffset), eax); __ mov(Operand(ecx), Factory::empty_fixed_array()); __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); // Set extra fields in the newly allocated object. // eax: initial map // ebx: JSObject // edi: start of next object { Label loop, entry; __ mov(Operand(edx), Factory::undefined_value()); __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); __ jmp(&entry); __ bind(&loop); __ mov(Operand(ecx, 0), edx); __ add(Operand(ecx), Immediate(kPointerSize)); __ bind(&entry); __ cmp(ecx, Operand(edi)); __ j(less, &loop); } // Mostly done with the JSObject. Add the heap tag and store the new top, so // that we can continue and jump into the continuation code at any time from // now on. Any failures need to undo the setting of the new top, so that the // heap is in a consistent state and verifiable. // eax: initial map // ebx: JSObject // edi: start of next object __ or_(Operand(ebx), Immediate(kHeapObjectTag)); __ mov(Operand::StaticVariable(new_space_allocation_top), edi); // Check if a properties array should be setup and allocate one if needed. // Otherwise initialize the properties to the empty_fixed_array as well. // eax: initial map // ebx: JSObject // edi: start of next object __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); __ test(edx, Operand(edx)); // Done if no unused properties are to be allocated. __ j(zero, &allocated); // Scale the number of elements by pointer size and add the header for // FixedArrays to the start of the next object calculation from above. // eax: initial map // ebx: JSObject // edi: start of next object (will be start of FixedArray) // edx: number of elements in properties array ASSERT(Heap::MaxHeapObjectSize() > (FixedArray::kHeaderSize + 255*kPointerSize)); __ lea(ecx, Operand(edi, edx, times_4, FixedArray::kHeaderSize)); __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); __ j(greater_equal, &undo_allocation); __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); // Initialize the FixedArray. // ebx: JSObject // edi: FixedArray // edx: number of elements // ecx: start of next object __ mov(eax, Factory::fixed_array_map()); __ mov(Operand(edi, JSObject::kMapOffset), eax); // setup the map __ mov(Operand(edi, Array::kLengthOffset), edx); // and length // Initialize the fields to undefined. // ebx: JSObject // edi: FixedArray // ecx: start of next object { Label loop, entry; __ mov(Operand(edx), Factory::undefined_value()); __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); __ jmp(&entry); __ bind(&loop); __ mov(Operand(eax, 0), edx); __ add(Operand(eax), Immediate(kPointerSize)); __ bind(&entry); __ cmp(eax, Operand(ecx)); __ j(less, &loop); } // Store the initialized FixedArray into the properties field of // the JSObject // ebx: JSObject // edi: FixedArray __ or_(Operand(edi), Immediate(kHeapObjectTag)); // add the heap tag __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi); // Continue with JSObject being successfully allocated // ebx: JSObject __ jmp(&allocated); // Undo the setting of the new top so that the heap is verifiable. For // example, the map's unused properties potentially do not match the // allocated objects unused properties. // ebx: JSObject (previous new top) __ bind(&undo_allocation); __ xor_(Operand(ebx), Immediate(kHeapObjectTag)); // clear the heap tag __ mov(Operand::StaticVariable(new_space_allocation_top), ebx); } // Allocate the new receiver object using the runtime call. // edi: function (constructor) __ bind(&rt_call); // Must restore edi (constructor) before calling runtime. __ mov(edi, Operand(esp, 0)); __ push(edi); __ CallRuntime(Runtime::kNewObject, 1); __ mov(ebx, Operand(eax)); // store result in ebx // New object allocated. // ebx: newly allocated object __ bind(&allocated); // Retrieve the function from the stack. __ pop(edi); // Retrieve smi-tagged arguments count from the stack. __ mov(eax, Operand(esp, 0)); __ shr(eax, kSmiTagSize); // Push the allocated receiver to the stack. We need two copies // because we may have to return the original one and the calling // conventions dictate that the called function pops the receiver. __ push(ebx); __ push(ebx); // Setup pointer to last argument. __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); // Copy arguments and receiver to the expression stack. Label loop, entry; __ mov(ecx, Operand(eax)); __ jmp(&entry); __ bind(&loop); __ push(Operand(ebx, ecx, times_4, 0)); __ bind(&entry); __ dec(ecx); __ j(greater_equal, &loop); // Call the function. Label return_site; ParameterCount actual(eax); __ InvokeFunction(edi, actual, CALL_FUNCTION); __ bind(&return_site); // Restore context from the frame. __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. Label use_receiver, exit; // If the result is a smi, it is *not* an object in the ECMA sense. __ test(eax, Immediate(kSmiTagMask)); __ j(zero, &use_receiver, not_taken); // If the type of the result (stored in its map) is less than // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); __ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ j(greater_equal, &exit, not_taken); // Throw away the result of the constructor invocation and use the // on-stack receiver as the result. __ bind(&use_receiver); __ mov(eax, Operand(esp, 0));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -