1// Copyright 2012 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/v8.h" 6 7#if V8_TARGET_ARCH_X87 8 9#include "src/ic/ic.h" 10#include "src/ic/ic-compiler.h" 11 12namespace v8 { 13namespace internal { 14 15#define __ ACCESS_MASM(masm) 16 17 18void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, 19 StrictMode strict_mode) { 20 // Return address is on the stack. 21 DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) && 22 !ebx.is(StoreDescriptor::NameRegister()) && 23 !ebx.is(StoreDescriptor::ValueRegister())); 24 __ pop(ebx); 25 __ push(StoreDescriptor::ReceiverRegister()); 26 __ push(StoreDescriptor::NameRegister()); 27 __ push(StoreDescriptor::ValueRegister()); 28 __ push(Immediate(Smi::FromInt(strict_mode))); 29 __ push(ebx); // return address 30 31 // Do tail-call to runtime routine. 32 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); 33} 34 35 36#undef __ 37#define __ ACCESS_MASM(masm()) 38 39Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, 40 CodeHandleList* handlers, 41 Handle<Name> name, 42 Code::StubType type, 43 IcCheckType check) { 44 Label miss; 45 46 if (check == PROPERTY && 47 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { 48 // In case we are compiling an IC for dictionary loads and stores, just 49 // check whether the name is unique. 50 if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) { 51 Register tmp = scratch1(); 52 __ JumpIfSmi(this->name(), &miss); 53 __ mov(tmp, FieldOperand(this->name(), HeapObject::kMapOffset)); 54 __ movzx_b(tmp, FieldOperand(tmp, Map::kInstanceTypeOffset)); 55 __ JumpIfNotUniqueNameInstanceType(tmp, &miss); 56 } else { 57 __ cmp(this->name(), Immediate(name)); 58 __ j(not_equal, &miss); 59 } 60 } 61 62 Label number_case; 63 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; 64 __ JumpIfSmi(receiver(), smi_target); 65 66 // Polymorphic keyed stores may use the map register 67 Register map_reg = scratch1(); 68 DCHECK(kind() != Code::KEYED_STORE_IC || 69 map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister())); 70 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); 71 int receiver_count = types->length(); 72 int number_of_handled_maps = 0; 73 for (int current = 0; current < receiver_count; ++current) { 74 Handle<HeapType> type = types->at(current); 75 Handle<Map> map = IC::TypeToMap(*type, isolate()); 76 if (!map->is_deprecated()) { 77 number_of_handled_maps++; 78 __ cmp(map_reg, map); 79 if (type->Is(HeapType::Number())) { 80 DCHECK(!number_case.is_unused()); 81 __ bind(&number_case); 82 } 83 __ j(equal, handlers->at(current)); 84 } 85 } 86 DCHECK(number_of_handled_maps != 0); 87 88 __ bind(&miss); 89 TailCallBuiltin(masm(), MissBuiltin(kind())); 90 91 // Return the generated code. 92 InlineCacheState state = 93 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; 94 return GetCode(kind(), type, name, state); 95} 96 97 98Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( 99 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, 100 MapHandleList* transitioned_maps) { 101 Label miss; 102 __ JumpIfSmi(receiver(), &miss, Label::kNear); 103 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); 104 for (int i = 0; i < receiver_maps->length(); ++i) { 105 __ cmp(scratch1(), receiver_maps->at(i)); 106 if (transitioned_maps->at(i).is_null()) { 107 __ j(equal, handler_stubs->at(i)); 108 } else { 109 Label next_map; 110 __ j(not_equal, &next_map, Label::kNear); 111 __ mov(transition_map(), Immediate(transitioned_maps->at(i))); 112 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 113 __ bind(&next_map); 114 } 115 } 116 __ bind(&miss); 117 TailCallBuiltin(masm(), MissBuiltin(kind())); 118 119 // Return the generated code. 120 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 121} 122 123 124#undef __ 125} 126} // namespace v8::internal 127 128#endif // V8_TARGET_ARCH_X87 129