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