📄 stub-cache-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 "ic-inl.h"#include "codegen-inl.h"#include "stub-cache.h"namespace v8 { namespace internal {#define __ masm->static void ProbeTable(MacroAssembler* masm, Code::Flags flags, StubCache::Table table, Register name, Register offset) { ExternalReference key_offset(SCTableReference::keyReference(table)); ExternalReference value_offset(SCTableReference::valueReference(table)); Label miss; // Save the offset on the stack. __ push(offset); // Check that the key in the entry matches the name. __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); __ j(not_equal, &miss, not_taken); // Get the code entry from the cache. __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); // Check that the flags match what we're looking for. __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); __ and_(offset, ~Code::kFlagsTypeMask); __ cmp(offset, flags); __ j(not_equal, &miss); // Restore offset and re-load code entry from cache. __ pop(offset); __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); // Jump to the first instruction in the code stub. __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag)); __ jmp(Operand(offset)); // Miss: Restore offset and fall through. __ bind(&miss); __ pop(offset);}void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags, Register receiver, Register name, Register scratch) { Label miss; // Make sure that code is valid. The shifting code relies on the // entry size being 8. ASSERT(sizeof(Entry) == 8); // Make sure the flags does not name a specific type. ASSERT(Code::ExtractTypeFromFlags(flags) == 0); // Make sure that there are no register conflicts. ASSERT(!scratch.is(receiver)); ASSERT(!scratch.is(name)); // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, &miss, not_taken); // Get the map of the receiver and compute the hash. __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); __ add(scratch, FieldOperand(name, String::kLengthOffset)); __ xor_(scratch, flags); __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); // Probe the primary table. ProbeTable(masm, flags, kPrimary, name, scratch); // Primary miss: Compute hash for secondary probe. __ sub(scratch, Operand(name)); __ add(Operand(scratch), Immediate(flags)); __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); // Probe the secondary table. ProbeTable(masm, flags, kSecondary, name, scratch); // Cache miss: Fall-through and let caller handle the miss by // entering the runtime system. __ bind(&miss);}void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, int index, Register prototype) { // Load the global or builtins object from the current context. __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); // Load the global context from the global or builtins object. __ mov(prototype, FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); // Load the function from the global context. __ mov(prototype, Operand(prototype, Context::SlotOffset(index))); // Load the initial map. The global functions all have initial maps. __ mov(prototype, FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); // Load the prototype from the initial map. __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));}void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, Register receiver, Register scratch, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the object is a JS array. __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); __ cmp(scratch, JS_ARRAY_TYPE); __ j(not_equal, miss_label, not_taken); // Load length directly from the JS array. __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); __ ret(0);}void StubCompiler::GenerateLoadShortStringLength(MacroAssembler* masm, Register receiver, Register scratch, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the object is a short string. __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); __ and_(scratch, kIsNotStringMask | kStringSizeMask); __ cmp(scratch, kStringTag | kShortStringTag); __ j(not_equal, miss_label, not_taken); // Load length directly from the string. __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); __ shr(eax, String::kShortLengthShift); __ shl(eax, kSmiTagSize); __ ret(0);}void StubCompiler::GenerateLoadMediumStringLength(MacroAssembler* masm, Register receiver, Register scratch, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the object is a short string. __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); __ and_(scratch, kIsNotStringMask | kStringSizeMask); __ cmp(scratch, kStringTag | kMediumStringTag); __ j(not_equal, miss_label, not_taken); // Load length directly from the string. __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); __ shr(eax, String::kMediumLengthShift); __ shl(eax, kSmiTagSize); __ ret(0);}void StubCompiler::GenerateLoadLongStringLength(MacroAssembler* masm, Register receiver, Register scratch, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the object is a short string. __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); __ and_(scratch, kIsNotStringMask | kStringSizeMask); __ cmp(scratch, kStringTag | kLongStringTag); __ j(not_equal, miss_label, not_taken); // Load length directly from the string. __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); __ shr(eax, String::kLongLengthShift); __ shl(eax, kSmiTagSize); __ ret(0);}void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, Register receiver, Register scratch1, Register scratch2, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the receiver is a function. __ mov(scratch1, FieldOperand(receiver, HeapObject::kMapOffset)); __ movzx_b(scratch2, FieldOperand(scratch1, Map::kInstanceTypeOffset)); __ cmp(scratch2, JS_FUNCTION_TYPE); __ j(not_equal, miss_label, not_taken); // Make sure that the function has an instance prototype. Label non_instance; __ movzx_b(scratch2, FieldOperand(scratch1, Map::kBitFieldOffset)); __ test(scratch2, Immediate(1 << Map::kHasNonInstancePrototype)); __ j(not_zero, &non_instance, not_taken); // Get the prototype or initial map from the function. __ mov(scratch1, FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset)); // If the prototype or initial map is the hole, don't return it and // simply miss the cache instead. This will allow us to allocate a // prototype object on-demand in the runtime system. __ cmp(Operand(scratch1), Immediate(Factory::the_hole_value())); __ j(equal, miss_label, not_taken); __ mov(eax, Operand(scratch1)); // If the function does not have an initial map, we're done. Label done; __ mov(scratch1, FieldOperand(eax, HeapObject::kMapOffset)); __ movzx_b(scratch2, FieldOperand(scratch1, Map::kInstanceTypeOffset)); __ cmp(scratch2, MAP_TYPE); __ j(not_equal, &done); // Get the prototype from the initial map. __ mov(eax, FieldOperand(eax, Map::kPrototypeOffset)); // All done: Return the prototype. __ bind(&done); __ ret(0); // Non-instance prototype: Fetch prototype from constructor field // in initial map. __ bind(&non_instance); __ mov(eax, FieldOperand(scratch1, Map::kConstructorOffset)); __ ret(0);}void StubCompiler::GenerateLoadField(MacroAssembler* masm, JSObject* object, JSObject* holder, Register receiver, Register scratch1, Register scratch2, int index, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the maps haven't changed. Register reg = __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label); // Get the properties array of the holder. __ mov(scratch1, FieldOperand(reg, JSObject::kPropertiesOffset)); // Return the value from the properties array. int offset = index * kPointerSize + Array::kHeaderSize; __ mov(eax, FieldOperand(scratch1, offset)); __ ret(0);}void StubCompiler::GenerateLoadCallback(MacroAssembler* masm, JSObject* object, JSObject* holder, Register receiver, Register name, Register scratch1, Register scratch2, AccessorInfo* callback, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the maps haven't changed. Register reg = __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label); // Push the arguments on the JS stack of the caller. __ pop(scratch2); // remove return address __ push(receiver); // receiver __ push(Immediate(Handle<AccessorInfo>(callback))); // callback data __ push(name); // name __ push(reg); // holder __ push(scratch2); // restore return address // Do tail-call to the runtime system. ExternalReference load_callback_property = ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); __ TailCallRuntime(load_callback_property, 4);}void StubCompiler::GenerateLoadConstant(MacroAssembler* masm, JSObject* object, JSObject* holder, Register receiver, Register scratch1, Register scratch2, Object* value, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the maps haven't changed. Register reg = __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label); // Return the constant value. __ mov(eax, Handle<Object>(value)); __ ret(0);}void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm, JSObject* object, JSObject* holder, Register receiver, Register name, Register scratch1, Register scratch2, Label* miss_label) { // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); __ j(zero, miss_label, not_taken); // Check that the maps haven't changed. Register reg = __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label); // Push the arguments on the JS stack of the caller. __ pop(scratch2); // remove return address __ push(receiver); // receiver __ push(reg); // holder __ push(name); // name __ push(scratch2); // restore return address // Do tail-call to the runtime system. ExternalReference load_ic_property = ExternalReference(IC_Utility(IC::kLoadInterceptorProperty)); __ TailCallRuntime(load_ic_property, 3);}void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); Code* code = NULL; if (kind == Code::LOAD_IC) { code = Builtins::builtin(Builtins::LoadIC_Miss); } else { code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); } Handle<Code> ic(code); __ jmp(ic, RelocInfo::CODE_TARGET);}void StubCompiler::GenerateStoreField(MacroAssembler* masm, JSObject* object, int index, Map* transition, Register receiver_reg, Register name_reg, Register scratch, Label* miss_label) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -