1 // Copyright 2016 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/builtins/builtins-utils.h" 6 #include "src/builtins/builtins.h" 7 #include "src/code-stub-assembler.h" 8 #include "src/ic/handler-compiler.h" 9 #include "src/ic/ic.h" 10 #include "src/ic/keyed-store-generic.h" 11 #include "src/objects-inl.h" 12 13 namespace v8 { 14 namespace internal { 15 16 TF_BUILTIN(KeyedLoadIC_IndexedString, CodeStubAssembler) { 17 typedef LoadWithVectorDescriptor Descriptor; 18 19 Node* receiver = Parameter(Descriptor::kReceiver); 20 Node* index = Parameter(Descriptor::kName); 21 Node* slot = Parameter(Descriptor::kSlot); 22 Node* vector = Parameter(Descriptor::kVector); 23 Node* context = Parameter(Descriptor::kContext); 24 25 Label miss(this); 26 27 Node* index_intptr = TryToIntptr(index, &miss); 28 Node* length = SmiUntag(LoadStringLength(receiver)); 29 GotoIf(UintPtrGreaterThanOrEqual(index_intptr, length), &miss); 30 31 Node* code = StringCharCodeAt(receiver, index_intptr, INTPTR_PARAMETERS); 32 Node* result = StringFromCharCode(code); 33 Return(result); 34 35 Bind(&miss); 36 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, index, slot, 37 vector); 38 } 39 40 TF_BUILTIN(KeyedLoadIC_Miss, CodeStubAssembler) { 41 typedef LoadWithVectorDescriptor Descriptor; 42 43 Node* receiver = Parameter(Descriptor::kReceiver); 44 Node* name = Parameter(Descriptor::kName); 45 Node* slot = Parameter(Descriptor::kSlot); 46 Node* vector = Parameter(Descriptor::kVector); 47 Node* context = Parameter(Descriptor::kContext); 48 49 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name, slot, 50 vector); 51 } 52 53 TF_BUILTIN(KeyedLoadIC_Slow, CodeStubAssembler) { 54 typedef LoadWithVectorDescriptor Descriptor; 55 56 Node* receiver = Parameter(Descriptor::kReceiver); 57 Node* name = Parameter(Descriptor::kName); 58 Node* context = Parameter(Descriptor::kContext); 59 60 TailCallRuntime(Runtime::kKeyedGetProperty, context, receiver, name); 61 } 62 63 void Builtins::Generate_KeyedStoreIC_Megamorphic( 64 compiler::CodeAssemblerState* state) { 65 KeyedStoreGenericGenerator::Generate(state, SLOPPY); 66 } 67 68 void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict( 69 compiler::CodeAssemblerState* state) { 70 KeyedStoreGenericGenerator::Generate(state, STRICT); 71 } 72 73 TF_BUILTIN(KeyedStoreIC_Miss, CodeStubAssembler) { 74 typedef StoreWithVectorDescriptor Descriptor; 75 76 Node* receiver = Parameter(Descriptor::kReceiver); 77 Node* name = Parameter(Descriptor::kName); 78 Node* value = Parameter(Descriptor::kValue); 79 Node* slot = Parameter(Descriptor::kSlot); 80 Node* vector = Parameter(Descriptor::kVector); 81 Node* context = Parameter(Descriptor::kContext); 82 83 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector, 84 receiver, name); 85 } 86 87 TF_BUILTIN(KeyedStoreIC_Slow, CodeStubAssembler) { 88 typedef StoreWithVectorDescriptor Descriptor; 89 90 Node* receiver = Parameter(Descriptor::kReceiver); 91 Node* name = Parameter(Descriptor::kName); 92 Node* value = Parameter(Descriptor::kValue); 93 Node* slot = Parameter(Descriptor::kSlot); 94 Node* vector = Parameter(Descriptor::kVector); 95 Node* context = Parameter(Descriptor::kContext); 96 97 // The slow case calls into the runtime to complete the store without causing 98 // an IC miss that would otherwise cause a transition to the generic stub. 99 TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, slot, vector, 100 receiver, name); 101 } 102 103 TF_BUILTIN(LoadGlobalIC_Miss, CodeStubAssembler) { 104 typedef LoadGlobalWithVectorDescriptor Descriptor; 105 106 Node* name = Parameter(Descriptor::kName); 107 Node* slot = Parameter(Descriptor::kSlot); 108 Node* vector = Parameter(Descriptor::kVector); 109 Node* context = Parameter(Descriptor::kContext); 110 111 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name, slot, vector); 112 } 113 114 TF_BUILTIN(LoadGlobalIC_Slow, CodeStubAssembler) { 115 typedef LoadGlobalWithVectorDescriptor Descriptor; 116 117 Node* name = Parameter(Descriptor::kName); 118 Node* slot = Parameter(Descriptor::kSlot); 119 Node* vector = Parameter(Descriptor::kVector); 120 Node* context = Parameter(Descriptor::kContext); 121 122 TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, name, slot, vector); 123 } 124 125 void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) { 126 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm); 127 } 128 129 TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) { 130 typedef LoadWithVectorDescriptor Descriptor; 131 132 Node* receiver = Parameter(Descriptor::kReceiver); 133 Node* name = Parameter(Descriptor::kName); 134 Node* slot = Parameter(Descriptor::kSlot); 135 Node* vector = Parameter(Descriptor::kVector); 136 Node* context = Parameter(Descriptor::kContext); 137 138 Label miss(this); 139 140 Node* proto_or_map = 141 LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset); 142 GotoIf(IsTheHole(proto_or_map), &miss); 143 144 Variable var_result(this, MachineRepresentation::kTagged, proto_or_map); 145 Label done(this, &var_result); 146 GotoIfNot(IsMap(proto_or_map), &done); 147 148 var_result.Bind(LoadMapPrototype(proto_or_map)); 149 Goto(&done); 150 151 Bind(&done); 152 Return(var_result.value()); 153 154 Bind(&miss); 155 TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector); 156 } 157 158 TF_BUILTIN(LoadIC_Miss, CodeStubAssembler) { 159 typedef LoadWithVectorDescriptor Descriptor; 160 161 Node* receiver = Parameter(Descriptor::kReceiver); 162 Node* name = Parameter(Descriptor::kName); 163 Node* slot = Parameter(Descriptor::kSlot); 164 Node* vector = Parameter(Descriptor::kVector); 165 Node* context = Parameter(Descriptor::kContext); 166 167 TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector); 168 } 169 170 TF_BUILTIN(LoadIC_Normal, CodeStubAssembler) { 171 typedef LoadWithVectorDescriptor Descriptor; 172 173 Node* receiver = Parameter(Descriptor::kReceiver); 174 Node* name = Parameter(Descriptor::kName); 175 Node* context = Parameter(Descriptor::kContext); 176 177 Label slow(this); 178 { 179 Node* properties = LoadProperties(receiver); 180 Variable var_name_index(this, MachineType::PointerRepresentation()); 181 Label found(this, &var_name_index); 182 NameDictionaryLookup<NameDictionary>(properties, name, &found, 183 &var_name_index, &slow); 184 Bind(&found); 185 { 186 Variable var_details(this, MachineRepresentation::kWord32); 187 Variable var_value(this, MachineRepresentation::kTagged); 188 LoadPropertyFromNameDictionary(properties, var_name_index.value(), 189 &var_details, &var_value); 190 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(), 191 context, receiver, &slow); 192 Return(value); 193 } 194 } 195 196 Bind(&slow); 197 TailCallRuntime(Runtime::kGetProperty, context, receiver, name); 198 } 199 200 TF_BUILTIN(LoadIC_Slow, CodeStubAssembler) { 201 typedef LoadWithVectorDescriptor Descriptor; 202 203 Node* receiver = Parameter(Descriptor::kReceiver); 204 Node* name = Parameter(Descriptor::kName); 205 Node* context = Parameter(Descriptor::kContext); 206 207 TailCallRuntime(Runtime::kGetProperty, context, receiver, name); 208 } 209 210 TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) { 211 typedef StoreWithVectorDescriptor Descriptor; 212 213 Node* receiver = Parameter(Descriptor::kReceiver); 214 Node* name = Parameter(Descriptor::kName); 215 Node* value = Parameter(Descriptor::kValue); 216 Node* slot = Parameter(Descriptor::kSlot); 217 Node* vector = Parameter(Descriptor::kVector); 218 Node* context = Parameter(Descriptor::kContext); 219 220 TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector, 221 receiver, name); 222 } 223 224 TF_BUILTIN(StoreIC_Normal, CodeStubAssembler) { 225 typedef StoreWithVectorDescriptor Descriptor; 226 227 Node* receiver = Parameter(Descriptor::kReceiver); 228 Node* name = Parameter(Descriptor::kName); 229 Node* value = Parameter(Descriptor::kValue); 230 Node* slot = Parameter(Descriptor::kSlot); 231 Node* vector = Parameter(Descriptor::kVector); 232 Node* context = Parameter(Descriptor::kContext); 233 234 Label slow(this); 235 { 236 Node* properties = LoadProperties(receiver); 237 Variable var_name_index(this, MachineType::PointerRepresentation()); 238 Label found(this, &var_name_index); 239 NameDictionaryLookup<NameDictionary>(properties, name, &found, 240 &var_name_index, &slow); 241 Bind(&found); 242 { 243 Node* details = LoadDetailsByKeyIndex<NameDictionary>( 244 properties, var_name_index.value()); 245 // Check that the property is a writable data property (no accessor). 246 const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask | 247 PropertyDetails::kAttributesReadOnlyMask; 248 STATIC_ASSERT(kData == 0); 249 GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), &slow); 250 StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(), 251 value); 252 Return(value); 253 } 254 } 255 256 Bind(&slow); 257 TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector, 258 receiver, name); 259 } 260 261 void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) { 262 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm); 263 } 264 265 } // namespace internal 266 } // namespace v8 267