| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #if V8_TARGET_ARCH_MIPS | 9 #if V8_TARGET_ARCH_MIPS |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 Register type, | 29 Register type, |
| 30 Label* global_object) { | 30 Label* global_object) { |
| 31 // Register usage: | 31 // Register usage: |
| 32 // type: holds the receiver instance type on entry. | 32 // type: holds the receiver instance type on entry. |
| 33 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_OBJECT_TYPE)); | 33 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_OBJECT_TYPE)); |
| 34 __ Branch(global_object, eq, type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 34 __ Branch(global_object, eq, type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
| 35 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_PROXY_TYPE)); | 35 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_PROXY_TYPE)); |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 // Generated code falls through if the receiver is a regular non-global | |
| 40 // JS object with slow properties and no interceptors. | |
| 41 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, | |
| 42 Register receiver, | |
| 43 Register elements, | |
| 44 Register scratch0, | |
| 45 Register scratch1, | |
| 46 Label* miss) { | |
| 47 // Register usage: | |
| 48 // receiver: holds the receiver on entry and is unchanged. | |
| 49 // elements: holds the property dictionary on fall through. | |
| 50 // Scratch registers: | |
| 51 // scratch0: used to holds the receiver map. | |
| 52 // scratch1: used to holds the receiver instance type, receiver bit mask | |
| 53 // and elements map. | |
| 54 | |
| 55 // Check that the receiver isn't a smi. | |
| 56 __ JumpIfSmi(receiver, miss); | |
| 57 | |
| 58 // Check that the receiver is a valid JS object. | |
| 59 __ GetObjectType(receiver, scratch0, scratch1); | |
| 60 __ Branch(miss, lt, scratch1, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
| 61 | |
| 62 // If this assert fails, we have to check upper bound too. | |
| 63 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); | |
| 64 | |
| 65 GenerateGlobalInstanceTypeCheck(masm, scratch1, miss); | |
| 66 | |
| 67 // Check that the global object does not require access checks. | |
| 68 __ lbu(scratch1, FieldMemOperand(scratch0, Map::kBitFieldOffset)); | |
| 69 __ And(scratch1, scratch1, Operand((1 << Map::kIsAccessCheckNeeded) | | |
| 70 (1 << Map::kHasNamedInterceptor))); | |
| 71 __ Branch(miss, ne, scratch1, Operand(zero_reg)); | |
| 72 | |
| 73 __ lw(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 74 __ lw(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
| 75 __ LoadRoot(scratch0, Heap::kHashTableMapRootIndex); | |
| 76 __ Branch(miss, ne, scratch1, Operand(scratch0)); | |
| 77 } | |
| 78 | |
| 79 | |
| 80 // Helper function used from LoadIC GenerateNormal. | 39 // Helper function used from LoadIC GenerateNormal. |
| 81 // | 40 // |
| 82 // elements: Property dictionary. It is not clobbered if a jump to the miss | 41 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 83 // label is done. | 42 // label is done. |
| 84 // name: Property name. It is not clobbered if a jump to the miss label is | 43 // name: Property name. It is not clobbered if a jump to the miss label is |
| 85 // done | 44 // done |
| 86 // result: Register for the result. It is only updated if a jump to the miss | 45 // result: Register for the result. It is only updated if a jump to the miss |
| 87 // label is not done. Can be the same as elements or name clobbering | 46 // label is not done. Can be the same as elements or name clobbering |
| 88 // one of these in the case of not jumping to the miss label. | 47 // one of these in the case of not jumping to the miss label. |
| 89 // The two scratch registers need to be different from elements, name and | 48 // The two scratch registers need to be different from elements, name and |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 286 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 328 masm->isolate()->stub_cache()->GenerateProbe( | 287 masm->isolate()->stub_cache()->GenerateProbe( |
| 329 masm, flags, receiver, name, a3, t0, t1, t2); | 288 masm, flags, receiver, name, a3, t0, t1, t2); |
| 330 | 289 |
| 331 // Cache miss: Jump to runtime. | 290 // Cache miss: Jump to runtime. |
| 332 GenerateMiss(masm); | 291 GenerateMiss(masm); |
| 333 } | 292 } |
| 334 | 293 |
| 335 | 294 |
| 336 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 295 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 337 // ----------- S t a t e ------------- | 296 Register dictionary = a0; |
| 338 // -- a2 : name | 297 ASSERT(!dictionary.is(ReceiverRegister())); |
| 339 // -- lr : return address | 298 ASSERT(!dictionary.is(NameRegister())); |
| 340 // -- a1 : receiver | |
| 341 // ----------------------------------- | |
| 342 ASSERT(a1.is(ReceiverRegister())); | |
| 343 ASSERT(a2.is(NameRegister())); | |
| 344 | 299 |
| 345 Label miss, slow; | 300 Label slow; |
| 346 | 301 |
| 347 GenerateNameDictionaryReceiverCheck(masm, a1, a0, a3, t0, &miss); | 302 __ lw(dictionary, |
| 348 | 303 FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); |
| 349 // a0: elements | 304 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), v0, a3, t0); |
| 350 GenerateDictionaryLoad(masm, &slow, a0, a2, v0, a3, t0); | |
| 351 __ Ret(); | 305 __ Ret(); |
| 352 | 306 |
| 353 // Dictionary load failed, go slow (but don't miss). | 307 // Dictionary load failed, go slow (but don't miss). |
| 354 __ bind(&slow); | 308 __ bind(&slow); |
| 355 GenerateRuntimeGetProperty(masm); | 309 GenerateRuntimeGetProperty(masm); |
| 356 | |
| 357 // Cache miss: Jump to runtime. | |
| 358 __ bind(&miss); | |
| 359 GenerateMiss(masm); | |
| 360 } | 310 } |
| 361 | 311 |
| 362 | 312 |
| 363 // A register that isn't one of the parameters to the load ic. | 313 // A register that isn't one of the parameters to the load ic. |
| 364 static const Register LoadIC_TempRegister() { return a3; } | 314 static const Register LoadIC_TempRegister() { return a3; } |
| 365 | 315 |
| 366 | 316 |
| 367 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 317 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 368 // The return address is in ra. | 318 // The return address is in ra. |
| 369 Isolate* isolate = masm->isolate(); | 319 Isolate* isolate = masm->isolate(); |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 masm->isolate()); | 1121 masm->isolate()); |
| 1172 __ TailCallExternalReference(ref, 3, 1); | 1122 __ TailCallExternalReference(ref, 3, 1); |
| 1173 } | 1123 } |
| 1174 | 1124 |
| 1175 | 1125 |
| 1176 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1126 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 1177 Label miss; | 1127 Label miss; |
| 1178 Register receiver = ReceiverRegister(); | 1128 Register receiver = ReceiverRegister(); |
| 1179 Register name = NameRegister(); | 1129 Register name = NameRegister(); |
| 1180 Register value = ValueRegister(); | 1130 Register value = ValueRegister(); |
| 1131 Register dictionary = a3; |
| 1181 ASSERT(receiver.is(a1)); | 1132 ASSERT(receiver.is(a1)); |
| 1182 ASSERT(name.is(a2)); | 1133 ASSERT(name.is(a2)); |
| 1183 ASSERT(value.is(a0)); | 1134 ASSERT(value.is(a0)); |
| 1184 | 1135 |
| 1185 GenerateNameDictionaryReceiverCheck(masm, receiver, a3, t0, t1, &miss); | 1136 __ lw(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 1186 | 1137 |
| 1187 GenerateDictionaryStore(masm, &miss, a3, name, value, t0, t1); | 1138 GenerateDictionaryStore(masm, &miss, dictionary, name, value, t0, t1); |
| 1188 Counters* counters = masm->isolate()->counters(); | 1139 Counters* counters = masm->isolate()->counters(); |
| 1189 __ IncrementCounter(counters->store_normal_hit(), 1, t0, t1); | 1140 __ IncrementCounter(counters->store_normal_hit(), 1, t0, t1); |
| 1190 __ Ret(); | 1141 __ Ret(); |
| 1191 | 1142 |
| 1192 __ bind(&miss); | 1143 __ bind(&miss); |
| 1193 __ IncrementCounter(counters->store_normal_miss(), 1, t0, t1); | 1144 __ IncrementCounter(counters->store_normal_miss(), 1, t0, t1); |
| 1194 GenerateMiss(masm); | 1145 GenerateMiss(masm); |
| 1195 } | 1146 } |
| 1196 | 1147 |
| 1197 | 1148 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 } else { | 1251 } else { |
| 1301 ASSERT(Assembler::IsBne(branch_instr)); | 1252 ASSERT(Assembler::IsBne(branch_instr)); |
| 1302 patcher.ChangeBranchCondition(eq); | 1253 patcher.ChangeBranchCondition(eq); |
| 1303 } | 1254 } |
| 1304 } | 1255 } |
| 1305 | 1256 |
| 1306 | 1257 |
| 1307 } } // namespace v8::internal | 1258 } } // namespace v8::internal |
| 1308 | 1259 |
| 1309 #endif // V8_TARGET_ARCH_MIPS | 1260 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |