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 #include "src/v8.h" | 6 #include "src/v8.h" |
7 | 7 |
8 #if V8_TARGET_ARCH_MIPS64 | 8 #if V8_TARGET_ARCH_MIPS64 |
9 | 9 |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 // In the case that the object is a value-wrapper object, | 152 // In the case that the object is a value-wrapper object, |
153 // we enter the runtime system to make sure that indexing into string | 153 // we enter the runtime system to make sure that indexing into string |
154 // objects work as intended. | 154 // objects work as intended. |
155 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 155 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
156 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 156 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
157 __ Branch(slow, lt, scratch, Operand(JS_OBJECT_TYPE)); | 157 __ Branch(slow, lt, scratch, Operand(JS_OBJECT_TYPE)); |
158 } | 158 } |
159 | 159 |
160 | 160 |
161 // Loads an indexed element from a fast case array. | 161 // Loads an indexed element from a fast case array. |
162 // If not_fast_array is NULL, doesn't perform the elements map check. | |
163 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, | 162 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, |
164 Register key, Register elements, | 163 Register key, Register elements, |
165 Register scratch1, Register scratch2, | 164 Register scratch1, Register scratch2, |
166 Register result, Label* not_fast_array, | 165 Register result, Label* slow) { |
167 Label* out_of_range) { | |
168 // Register use: | 166 // Register use: |
169 // | 167 // |
170 // receiver - holds the receiver on entry. | 168 // receiver - holds the receiver on entry. |
171 // Unchanged unless 'result' is the same register. | 169 // Unchanged unless 'result' is the same register. |
172 // | 170 // |
173 // key - holds the smi key on entry. | 171 // key - holds the smi key on entry. |
174 // Unchanged unless 'result' is the same register. | 172 // Unchanged unless 'result' is the same register. |
175 // | 173 // |
176 // elements - holds the elements of the receiver on exit. | |
177 // | |
178 // result - holds the result on exit if the load succeeded. | 174 // result - holds the result on exit if the load succeeded. |
179 // Allowed to be the the same as 'receiver' or 'key'. | 175 // Allowed to be the the same as 'receiver' or 'key'. |
180 // Unchanged on bailout so 'receiver' and 'key' can be safely | 176 // Unchanged on bailout so 'receiver' and 'key' can be safely |
181 // used by further computation. | 177 // used by further computation. |
182 // | 178 // |
183 // Scratch registers: | 179 // Scratch registers: |
184 // | 180 // |
185 // scratch1 - used to hold elements map and elements length. | 181 // elements - holds the elements of the receiver and its prototypes. |
186 // Holds the elements map if not_fast_array branch is taken. | |
187 // | 182 // |
188 // scratch2 - used to hold the loaded value. | 183 // scratch1 - used to hold elements length, bit fields, base addresses. |
| 184 // |
| 185 // scratch2 - used to hold maps, prototypes, and the loaded value. |
| 186 Label check_prototypes, check_next_prototype; |
| 187 Label done, in_bounds, return_undefined; |
189 | 188 |
190 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 189 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
191 if (not_fast_array != NULL) { | 190 __ AssertFastElements(elements); |
192 // Check that the object is in fast mode (not dictionary). | |
193 __ ld(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
194 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); | |
195 __ Branch(not_fast_array, ne, scratch1, Operand(at)); | |
196 } else { | |
197 __ AssertFastElements(elements); | |
198 } | |
199 | 191 |
200 // Check that the key (index) is within bounds. | 192 // Check that the key (index) is within bounds. |
201 __ ld(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 193 __ ld(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
202 __ Branch(out_of_range, hs, key, Operand(scratch1)); | 194 __ Branch(&in_bounds, lo, key, Operand(scratch1)); |
| 195 // Out-of-bounds. Check the prototype chain to see if we can just return |
| 196 // 'undefined'. |
| 197 // Negative keys can't take the fast OOB path. |
| 198 __ Branch(slow, lt, key, Operand(zero_reg)); |
| 199 __ bind(&check_prototypes); |
| 200 __ ld(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 201 __ bind(&check_next_prototype); |
| 202 __ ld(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); |
| 203 // scratch2: current prototype |
| 204 __ LoadRoot(at, Heap::kNullValueRootIndex); |
| 205 __ Branch(&return_undefined, eq, scratch2, Operand(at)); |
| 206 __ ld(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); |
| 207 __ ld(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); |
| 208 // elements: elements of current prototype |
| 209 // scratch2: map of current prototype |
| 210 __ lbu(scratch1, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); |
| 211 __ Branch(slow, lo, scratch1, Operand(JS_OBJECT_TYPE)); |
| 212 __ lbu(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset)); |
| 213 __ And(at, scratch1, Operand((1 << Map::kIsAccessCheckNeeded) | |
| 214 (1 << Map::kHasIndexedInterceptor))); |
| 215 __ Branch(slow, ne, at, Operand(zero_reg)); |
| 216 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); |
| 217 __ Branch(slow, ne, elements, Operand(at)); |
| 218 __ Branch(&check_next_prototype); |
203 | 219 |
| 220 __ bind(&return_undefined); |
| 221 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 222 __ Branch(&done); |
| 223 |
| 224 __ bind(&in_bounds); |
204 // Fast case: Do the load. | 225 // Fast case: Do the load. |
205 __ Daddu(scratch1, elements, | 226 __ Daddu(scratch1, elements, |
206 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 227 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
207 // The key is a smi. | 228 // The key is a smi. |
208 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 229 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
209 __ SmiScale(at, key, kPointerSizeLog2); | 230 __ SmiScale(at, key, kPointerSizeLog2); |
210 __ daddu(at, at, scratch1); | 231 __ daddu(at, at, scratch1); |
211 __ ld(scratch2, MemOperand(at)); | 232 __ ld(scratch2, MemOperand(at)); |
212 | 233 |
213 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 234 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
214 // In case the loaded value is the_hole we have to consult GetProperty | 235 // In case the loaded value is the_hole we have to check the prototype chain. |
215 // to ensure the prototype chain is searched. | 236 __ Branch(&check_prototypes, eq, scratch2, Operand(at)); |
216 __ Branch(out_of_range, eq, scratch2, Operand(at)); | 237 __ Move(result, scratch2); |
217 __ mov(result, scratch2); | 238 __ bind(&done); |
218 } | 239 } |
219 | 240 |
220 | 241 |
221 // Checks whether a key is an array index string or a unique name. | 242 // Checks whether a key is an array index string or a unique name. |
222 // Falls through if a key is a unique name. | 243 // Falls through if a key is a unique name. |
223 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, | 244 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, |
224 Register map, Register hash, | 245 Register map, Register hash, |
225 Label* index_string, Label* not_unique) { | 246 Label* index_string, Label* not_unique) { |
226 // The key is not a smi. | 247 // The key is not a smi. |
227 Label unique; | 248 Label unique; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 __ bind(&index_smi); | 490 __ bind(&index_smi); |
470 // Now the key is known to be a smi. This place is also jumped to from below | 491 // Now the key is known to be a smi. This place is also jumped to from below |
471 // where a numeric string is converted to a smi. | 492 // where a numeric string is converted to a smi. |
472 | 493 |
473 GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, | 494 GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, |
474 Map::kHasIndexedInterceptor, &slow); | 495 Map::kHasIndexedInterceptor, &slow); |
475 | 496 |
476 // Check the receiver's map to see if it has fast elements. | 497 // Check the receiver's map to see if it has fast elements. |
477 __ CheckFastElements(a0, a3, &check_number_dictionary); | 498 __ CheckFastElements(a0, a3, &check_number_dictionary); |
478 | 499 |
479 GenerateFastArrayLoad(masm, receiver, key, a0, a3, a4, v0, NULL, &slow); | 500 GenerateFastArrayLoad(masm, receiver, key, a0, a3, a4, v0, &slow); |
480 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a4, a3); | 501 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a4, a3); |
481 __ Ret(); | 502 __ Ret(); |
482 | 503 |
483 __ bind(&check_number_dictionary); | 504 __ bind(&check_number_dictionary); |
484 __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 505 __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
485 __ ld(a3, FieldMemOperand(a4, JSObject::kMapOffset)); | 506 __ ld(a3, FieldMemOperand(a4, JSObject::kMapOffset)); |
486 | 507 |
487 // Check whether the elements is a number dictionary. | 508 // Check whether the elements is a number dictionary. |
488 // a3: elements map | 509 // a3: elements map |
489 // a4: elements | 510 // a4: elements |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 patcher.ChangeBranchCondition(ne); | 1053 patcher.ChangeBranchCondition(ne); |
1033 } else { | 1054 } else { |
1034 DCHECK(Assembler::IsBne(branch_instr)); | 1055 DCHECK(Assembler::IsBne(branch_instr)); |
1035 patcher.ChangeBranchCondition(eq); | 1056 patcher.ChangeBranchCondition(eq); |
1036 } | 1057 } |
1037 } | 1058 } |
1038 } | 1059 } |
1039 } // namespace v8::internal | 1060 } // namespace v8::internal |
1040 | 1061 |
1041 #endif // V8_TARGET_ARCH_MIPS64 | 1062 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |