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_X64 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 // Return address is on the stack. 21 DCHECK(!rbx.is(StoreDescriptor::ReceiverRegister()) && 22 !rbx.is(StoreDescriptor::NameRegister()) && 23 !rbx.is(StoreDescriptor::ValueRegister())); 24 25 __ PopReturnAddressTo(rbx); 26 __ Push(StoreDescriptor::ReceiverRegister()); 27 __ Push(StoreDescriptor::NameRegister()); 28 __ Push(StoreDescriptor::ValueRegister()); 29 __ Push(Smi::FromInt(strict_mode)); 30 __ PushReturnAddressFrom(rbx); 31 32 // Do tail-call to runtime routine. 33 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); 34 } 35 36 37 #undef __ 38 #define __ ACCESS_MASM(masm()) 39 40 41 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( 42 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, 43 MapHandleList* transitioned_maps) { 44 Label miss; 45 __ JumpIfSmi(receiver(), &miss, Label::kNear); 46 47 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); 48 int receiver_count = receiver_maps->length(); 49 for (int i = 0; i < receiver_count; ++i) { 50 // Check map and tail call if there's a match 51 __ Cmp(scratch1(), receiver_maps->at(i)); 52 if (transitioned_maps->at(i).is_null()) { 53 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); 54 } else { 55 Label next_map; 56 __ j(not_equal, &next_map, Label::kNear); 57 __ Move(transition_map(), transitioned_maps->at(i), 58 RelocInfo::EMBEDDED_OBJECT); 59 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 60 __ bind(&next_map); 61 } 62 } 63 64 __ bind(&miss); 65 66 TailCallBuiltin(masm(), MissBuiltin(kind())); 67 68 // Return the generated code. 69 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 70 } 71 72 73 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, 74 CodeHandleList* handlers, 75 Handle<Name> name, 76 Code::StubType type, 77 IcCheckType check) { 78 Label miss; 79 80 if (check == PROPERTY && 81 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { 82 // In case we are compiling an IC for dictionary loads and stores, just 83 // check whether the name is unique. 84 if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) { 85 Register tmp = scratch1(); 86 __ JumpIfSmi(this->name(), &miss); 87 __ movp(tmp, FieldOperand(this->name(), HeapObject::kMapOffset)); 88 __ movzxbp(tmp, FieldOperand(tmp, Map::kInstanceTypeOffset)); 89 __ JumpIfNotUniqueNameInstanceType(tmp, &miss); 90 } else { 91 __ Cmp(this->name(), name); 92 __ j(not_equal, &miss); 93 } 94 } 95 96 Label number_case; 97 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; 98 __ JumpIfSmi(receiver(), smi_target); 99 100 // Polymorphic keyed stores may use the map register 101 Register map_reg = scratch1(); 102 DCHECK(kind() != Code::KEYED_STORE_IC || 103 map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister())); 104 __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); 105 int receiver_count = types->length(); 106 int number_of_handled_maps = 0; 107 for (int current = 0; current < receiver_count; ++current) { 108 Handle<HeapType> type = types->at(current); 109 Handle<Map> map = IC::TypeToMap(*type, isolate()); 110 if (!map->is_deprecated()) { 111 number_of_handled_maps++; 112 // Check map and tail call if there's a match 113 __ Cmp(map_reg, map); 114 if (type->Is(HeapType::Number())) { 115 DCHECK(!number_case.is_unused()); 116 __ bind(&number_case); 117 } 118 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); 119 } 120 } 121 DCHECK(number_of_handled_maps > 0); 122 123 __ bind(&miss); 124 TailCallBuiltin(masm(), MissBuiltin(kind())); 125 126 // Return the generated code. 127 InlineCacheState state = 128 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; 129 return GetCode(kind(), type, name, state); 130 } 131 132 133 #undef __ 134 } 135 } // namespace v8::internal 136 137 #endif // V8_TARGET_ARCH_X64 138