📄 ic-arm.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 "ic-inl.h"#include "runtime.h"#include "stub-cache.h"namespace v8 { namespace internal {// ----------------------------------------------------------------------------// Static IC stub generators.//#define __ masm->// Helper function used from LoadIC/CallIC GenerateNormal.static void GenerateDictionaryLoad(MacroAssembler* masm, Label* done_label, Label* miss_label, Register t0, Register t1) { // Register use: // // t0 - used to hold the property dictionary. // // t1 - initially the receiver // - used for the index into the property dictionary // - holds the result on exit. // // r3 - used as temporary and to hold the capacity of the property // dictionary. // // r2 - holds the name of the property and is unchanges. // Check for the absence of an interceptor. // Load the map into t0. __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); // Test the has_named_interceptor bit in the map. __ ldr(t0, FieldMemOperand(t1, Map::kInstanceAttributesOffset)); __ tst(t0, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8)))); // Jump to miss if the interceptor bit is set. __ b(ne, miss_label); // Check that the properties array is a dictionary. __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset)); __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset)); __ cmp(r3, Operand(Factory::hash_table_map())); __ b(ne, miss_label); // Compute the capacity mask. const int kCapacityOffset = Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize; __ ldr(r3, FieldMemOperand(t0, kCapacityOffset)); __ mov(r3, Operand(r3, ASR, kSmiTagSize)); // convert smi to int __ sub(r3, r3, Operand(1)); const int kElementsStartOffset = Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize; // Generate an unrolled loop that performs a few probes before // giving up. Measurements done on Gmail indicate that 2 probes // cover ~93% of loads from dictionaries. static const int kProbes = 4; for (int i = 0; i < kProbes; i++) { // Compute the masked index: (hash + i + i * i) & mask. __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset)); if (i > 0) __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i))); __ and_(t1, t1, Operand(r3)); // Scale the index by multiplying by the element size. ASSERT(Dictionary::kElementSize == 3); __ add(t1, t1, Operand(t1, LSL, 1)); // t1 = t1 * 3 // Check if the key is identical to the name. __ add(t1, t0, Operand(t1, LSL, 2)); __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset)); __ cmp(r2, Operand(ip)); if (i != kProbes - 1) { __ b(eq, done_label); } else { __ b(ne, miss_label); } } // Check that the value is a normal property. __ bind(done_label); // t1 == t0 + 4*index __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize)); __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); __ b(ne, miss_label); // Get the value at the masked, scaled index and return. __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize));}void LoadIC::GenerateArrayLength(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address // -- [sp] : receiver // ----------------------------------- Label miss; __ ldr(r0, MemOperand(sp, 0)); // Check that the receiver isn't a smi. __ tst(r0, Operand(kSmiTagMask)); __ b(eq, &miss); // Check that the object is a JS array. __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); __ cmp(r1, Operand(JS_ARRAY_TYPE)); __ b(ne, &miss); // Load length directly from the JS array. __ ldr(r0, FieldMemOperand(r0, JSArray::kLengthOffset)); __ Ret(); // Cache miss: Jump to runtime. __ bind(&miss); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss)); __ Jump(ic, RelocInfo::CODE_TARGET);}void LoadIC::GenerateShortStringLength(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address // -- [sp] : receiver // ----------------------------------- Label miss; __ ldr(r0, MemOperand(sp, 0)); // Check that the receiver isn't a smi. __ tst(r0, Operand(kSmiTagMask)); __ b(eq, &miss); // Check that the object is a short string. __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); __ and_(r1, r1, Operand(kIsNotStringMask | kStringSizeMask)); // The cast is to resolve the overload for the argument of 0x0. __ cmp(r1, Operand(static_cast<int32_t>(kStringTag | kShortStringTag))); __ b(ne, &miss); // Load length directly from the string. __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset)); __ mov(r0, Operand(r0, LSR, String::kShortLengthShift)); __ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ Ret(); // Cache miss: Jump to runtime. __ bind(&miss); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss)); __ Jump(ic, RelocInfo::CODE_TARGET);}void LoadIC::GenerateMediumStringLength(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address // -- [sp] : receiver // ----------------------------------- Label miss; __ ldr(r0, MemOperand(sp, 0)); // Check that the receiver isn't a smi. __ tst(r0, Operand(kSmiTagMask)); __ b(eq, &miss); // Check that the object is a medium string. __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); __ and_(r1, r1, Operand(kIsNotStringMask | kStringSizeMask)); __ cmp(r1, Operand(kStringTag | kMediumStringTag)); __ b(ne, &miss); // Load length directly from the string. __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset)); __ mov(r0, Operand(r0, LSR, String::kMediumLengthShift)); __ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ Ret(); // Cache miss: Jump to runtime. __ bind(&miss); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss)); __ Jump(ic, RelocInfo::CODE_TARGET);}void LoadIC::GenerateLongStringLength(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address // -- [sp] : receiver // ----------------------------------- Label miss; __ ldr(r0, MemOperand(sp, 0)); // Check that the receiver isn't a smi. __ tst(r0, Operand(kSmiTagMask)); __ b(eq, &miss); // Check that the object is a long string. __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); __ and_(r1, r1, Operand(kIsNotStringMask | kStringSizeMask)); __ cmp(r1, Operand(kStringTag | kLongStringTag)); __ b(ne, &miss); // Load length directly from the string. __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset)); __ mov(r0, Operand(r0, LSR, String::kLongLengthShift)); __ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ Ret(); // Cache miss: Jump to runtime. __ bind(&miss); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss)); __ Jump(ic, RelocInfo::CODE_TARGET);}void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address // -- [sp] : receiver // ----------------------------------- // NOTE: Right now, this code always misses on ARM which is // sub-optimal. We should port the fast case code from IA-32. Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss)); __ Jump(ic, RelocInfo::CODE_TARGET);}// Defined in ic.cc.Object* CallIC_Miss(Arguments args);void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- // -- lr: return address // ----------------------------------- Label number, non_number, non_string, boolean, probe, miss; // Get the receiver of the function from the stack into r1. __ ldr(r1, MemOperand(sp, argc * kPointerSize)); // Get the name of the function from the stack; 1 ~ receiver. __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize)); // Probe the stub cache.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -