OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 } | 222 } |
223 #endif | 223 #endif |
224 | 224 |
225 | 225 |
226 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 226 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
227 // ----------- S t a t e ------------- | 227 // ----------- S t a t e ------------- |
228 // -- esp[0] : return address | 228 // -- esp[0] : return address |
229 // -- esp[4] : name | 229 // -- esp[4] : name |
230 // -- esp[8] : receiver | 230 // -- esp[8] : receiver |
231 // ----------------------------------- | 231 // ----------------------------------- |
232 Label slow, fast, check_string, index_int, index_string; | 232 Label slow, check_string, index_int, index_string, check_pixel_array; |
233 | 233 |
234 // Load name and receiver. | 234 // Load name and receiver. |
235 __ mov(eax, (Operand(esp, kPointerSize))); | 235 __ mov(eax, (Operand(esp, kPointerSize))); |
236 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); | 236 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); |
237 | 237 |
238 // Check that the object isn't a smi. | 238 // Check that the object isn't a smi. |
239 __ test(ecx, Immediate(kSmiTagMask)); | 239 __ test(ecx, Immediate(kSmiTagMask)); |
240 __ j(zero, &slow, not_taken); | 240 __ j(zero, &slow, not_taken); |
241 | 241 |
242 // Get the map of the receiver. | 242 // Get the map of the receiver. |
(...skipping 14 matching lines...) Expand all Loading... |
257 __ j(less, &slow, not_taken); | 257 __ j(less, &slow, not_taken); |
258 // Check that the key is a smi. | 258 // Check that the key is a smi. |
259 __ test(eax, Immediate(kSmiTagMask)); | 259 __ test(eax, Immediate(kSmiTagMask)); |
260 __ j(not_zero, &check_string, not_taken); | 260 __ j(not_zero, &check_string, not_taken); |
261 __ sar(eax, kSmiTagSize); | 261 __ sar(eax, kSmiTagSize); |
262 // Get the elements array of the object. | 262 // Get the elements array of the object. |
263 __ bind(&index_int); | 263 __ bind(&index_int); |
264 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); | 264 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); |
265 // Check that the object is in fast mode (not dictionary). | 265 // Check that the object is in fast mode (not dictionary). |
266 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 266 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
267 Immediate(Factory::hash_table_map())); | 267 Immediate(Factory::fixed_array_map())); |
268 __ j(equal, &slow, not_taken); | 268 __ j(not_equal, &check_pixel_array); |
269 // Check that the key (index) is within bounds. | 269 // Check that the key (index) is within bounds. |
270 __ cmp(eax, FieldOperand(ecx, Array::kLengthOffset)); | 270 __ cmp(eax, FieldOperand(ecx, Array::kLengthOffset)); |
271 __ j(below, &fast, taken); | 271 __ j(above_equal, &slow); |
| 272 // Fast case: Do the load. |
| 273 __ mov(eax, |
| 274 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); |
| 275 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); |
| 276 // In case the loaded value is the_hole we have to consult GetProperty |
| 277 // to ensure the prototype chain is searched. |
| 278 __ j(equal, &slow); |
| 279 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
| 280 __ ret(0); |
| 281 |
| 282 // Check whether the elements is a pixel array. |
| 283 // eax: untagged index |
| 284 // ecx: elements array |
| 285 __ bind(&check_pixel_array); |
| 286 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
| 287 Immediate(Factory::pixel_array_map())); |
| 288 __ j(not_equal, &slow); |
| 289 __ cmp(eax, FieldOperand(ecx, PixelArray::kLengthOffset)); |
| 290 __ j(above_equal, &slow); |
| 291 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
| 292 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); |
| 293 __ shl(eax, kSmiTagSize); |
| 294 __ ret(0); |
| 295 |
| 296 |
272 // Slow case: Load name and receiver from stack and jump to runtime. | 297 // Slow case: Load name and receiver from stack and jump to runtime. |
273 __ bind(&slow); | 298 __ bind(&slow); |
274 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); | 299 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
275 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 300 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); |
276 | 301 |
277 __ bind(&check_string); | 302 __ bind(&check_string); |
278 // The key is not a smi. | 303 // The key is not a smi. |
279 // Is it a string? | 304 // Is it a string? |
280 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); | 305 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); |
281 __ j(above_equal, &slow); | 306 __ j(above_equal, &slow); |
(...skipping 21 matching lines...) Expand all Loading... |
303 (1 << (String::kShortLengthShift - String::kHashShift))); | 328 (1 << (String::kShortLengthShift - String::kHashShift))); |
304 __ bind(&index_string); | 329 __ bind(&index_string); |
305 const int kLengthFieldLimit = | 330 const int kLengthFieldLimit = |
306 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; | 331 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; |
307 __ cmp(ebx, kLengthFieldLimit); | 332 __ cmp(ebx, kLengthFieldLimit); |
308 __ j(above_equal, &slow); | 333 __ j(above_equal, &slow); |
309 __ mov(eax, Operand(ebx)); | 334 __ mov(eax, Operand(ebx)); |
310 __ and_(eax, (1 << String::kShortLengthShift) - 1); | 335 __ and_(eax, (1 << String::kShortLengthShift) - 1); |
311 __ shr(eax, String::kLongLengthShift); | 336 __ shr(eax, String::kLongLengthShift); |
312 __ jmp(&index_int); | 337 __ jmp(&index_int); |
313 // Fast case: Do the load. | |
314 __ bind(&fast); | |
315 __ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag)); | |
316 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); | |
317 // In case the loaded value is the_hole we have to consult GetProperty | |
318 // to ensure the prototype chain is searched. | |
319 __ j(equal, &slow, not_taken); | |
320 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | |
321 __ ret(0); | |
322 } | 338 } |
323 | 339 |
324 | 340 |
325 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 341 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
326 // ----------- S t a t e ------------- | 342 // ----------- S t a t e ------------- |
327 // -- eax : value | 343 // -- eax : value |
328 // -- esp[0] : return address | 344 // -- esp[0] : return address |
329 // -- esp[4] : key | 345 // -- esp[4] : key |
330 // -- esp[8] : receiver | 346 // -- esp[8] : receiver |
331 // ----------------------------------- | 347 // ----------------------------------- |
332 Label slow, fast, array, extra; | 348 Label slow, fast, array, extra, check_pixel_array; |
333 | 349 |
334 // Get the receiver from the stack. | 350 // Get the receiver from the stack. |
335 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key | 351 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key |
336 // Check that the object isn't a smi. | 352 // Check that the object isn't a smi. |
337 __ test(edx, Immediate(kSmiTagMask)); | 353 __ test(edx, Immediate(kSmiTagMask)); |
338 __ j(zero, &slow, not_taken); | 354 __ j(zero, &slow, not_taken); |
339 // Get the map from the receiver. | 355 // Get the map from the receiver. |
340 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 356 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
341 // Check that the receiver does not require access checks. We need | 357 // Check that the receiver does not require access checks. We need |
342 // to do this because this generic stub does not perform map checks. | 358 // to do this because this generic stub does not perform map checks. |
(...skipping 14 matching lines...) Expand all Loading... |
357 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 373 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
358 __ j(less, &slow, not_taken); | 374 __ j(less, &slow, not_taken); |
359 | 375 |
360 // Object case: Check key against length in the elements array. | 376 // Object case: Check key against length in the elements array. |
361 // eax: value | 377 // eax: value |
362 // edx: JSObject | 378 // edx: JSObject |
363 // ebx: index (as a smi) | 379 // ebx: index (as a smi) |
364 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 380 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
365 // Check that the object is in fast mode (not dictionary). | 381 // Check that the object is in fast mode (not dictionary). |
366 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 382 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
367 Immediate(Factory::hash_table_map())); | 383 Immediate(Factory::fixed_array_map())); |
368 __ j(equal, &slow, not_taken); | 384 __ j(not_equal, &check_pixel_array, not_taken); |
369 // Untag the key (for checking against untagged length in the fixed array). | 385 // Untag the key (for checking against untagged length in the fixed array). |
370 __ mov(edx, Operand(ebx)); | 386 __ mov(edx, Operand(ebx)); |
371 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison | 387 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison |
372 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); | 388 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); |
373 // eax: value | 389 // eax: value |
374 // ecx: FixedArray | 390 // ecx: FixedArray |
375 // ebx: index (as a smi) | 391 // ebx: index (as a smi) |
376 __ j(below, &fast, taken); | 392 __ j(below, &fast, taken); |
377 | 393 |
378 | |
379 // Slow case: Push extra copies of the arguments (3). | 394 // Slow case: Push extra copies of the arguments (3). |
380 __ bind(&slow); | 395 __ bind(&slow); |
381 __ pop(ecx); | 396 __ pop(ecx); |
382 __ push(Operand(esp, 1 * kPointerSize)); | 397 __ push(Operand(esp, 1 * kPointerSize)); |
383 __ push(Operand(esp, 1 * kPointerSize)); | 398 __ push(Operand(esp, 1 * kPointerSize)); |
384 __ push(eax); | 399 __ push(eax); |
385 __ push(ecx); | 400 __ push(ecx); |
386 // Do tail-call to runtime routine. | 401 // Do tail-call to runtime routine. |
387 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); | 402 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); |
388 | 403 |
| 404 // Check whether the elements is a pixel array. |
| 405 // eax: value |
| 406 // ecx: elements array |
| 407 // ebx: index (as a smi) |
| 408 __ bind(&check_pixel_array); |
| 409 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
| 410 Immediate(Factory::pixel_array_map())); |
| 411 __ j(not_equal, &slow); |
| 412 // Check that the value is a smi. If a conversion is needed call into the |
| 413 // runtime to convert and clamp. |
| 414 __ test(eax, Immediate(kSmiTagMask)); |
| 415 __ j(not_zero, &slow); |
| 416 __ sar(ebx, kSmiTagSize); // Untag the index. |
| 417 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); |
| 418 __ j(above_equal, &slow); |
| 419 __ sar(eax, kSmiTagSize); // Untag the value. |
| 420 { // Clamp the value to [0..255]. |
| 421 Label done, check_255; |
| 422 __ cmp(eax, 0); |
| 423 __ j(greater_equal, &check_255); |
| 424 __ mov(eax, Immediate(0)); |
| 425 __ jmp(&done); |
| 426 __ bind(&check_255); |
| 427 __ cmp(eax, 255); |
| 428 __ j(less_equal, &done); |
| 429 __ mov(eax, Immediate(255)); |
| 430 __ bind(&done); |
| 431 } |
| 432 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
| 433 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); |
| 434 __ ret(0); |
389 | 435 |
390 // Extra capacity case: Check if there is extra capacity to | 436 // Extra capacity case: Check if there is extra capacity to |
391 // perform the store and update the length. Used for adding one | 437 // perform the store and update the length. Used for adding one |
392 // element to the array by writing to array[array.length]. | 438 // element to the array by writing to array[array.length]. |
393 __ bind(&extra); | 439 __ bind(&extra); |
394 // eax: value | 440 // eax: value |
395 // edx: JSArray | 441 // edx: JSArray |
396 // ecx: FixedArray | 442 // ecx: FixedArray |
397 // ebx: index (as a smi) | 443 // ebx: index (as a smi) |
398 // flags: compare (ebx, edx.length()) | 444 // flags: compare (ebx, edx.length()) |
(...skipping 10 matching lines...) Expand all Loading... |
409 | 455 |
410 // Array case: Get the length and the elements array from the JS | 456 // Array case: Get the length and the elements array from the JS |
411 // array. Check that the array is in fast mode; if it is the | 457 // array. Check that the array is in fast mode; if it is the |
412 // length is always a smi. | 458 // length is always a smi. |
413 __ bind(&array); | 459 __ bind(&array); |
414 // eax: value | 460 // eax: value |
415 // edx: JSArray | 461 // edx: JSArray |
416 // ebx: index (as a smi) | 462 // ebx: index (as a smi) |
417 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 463 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
418 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 464 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
419 Immediate(Factory::hash_table_map())); | 465 Immediate(Factory::fixed_array_map())); |
420 __ j(equal, &slow, not_taken); | 466 __ j(not_equal, &check_pixel_array); |
421 | 467 |
422 // Check the key against the length in the array, compute the | 468 // Check the key against the length in the array, compute the |
423 // address to store into and fall through to fast case. | 469 // address to store into and fall through to fast case. |
424 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); | 470 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); |
425 __ j(above_equal, &extra, not_taken); | 471 __ j(above_equal, &extra, not_taken); |
426 | 472 |
427 | |
428 // Fast case: Do the store. | 473 // Fast case: Do the store. |
429 __ bind(&fast); | 474 __ bind(&fast); |
430 // eax: value | 475 // eax: value |
431 // ecx: FixedArray | 476 // ecx: FixedArray |
432 // ebx: index (as a smi) | 477 // ebx: index (as a smi) |
433 __ mov(Operand(ecx, ebx, times_2, Array::kHeaderSize - kHeapObjectTag), eax); | 478 __ mov(Operand(ecx, ebx, times_2, Array::kHeaderSize - kHeapObjectTag), eax); |
434 // Update write barrier for the elements array address. | 479 // Update write barrier for the elements array address. |
435 __ mov(edx, Operand(eax)); | 480 __ mov(edx, Operand(eax)); |
436 __ RecordWrite(ecx, 0, edx, ebx); | 481 __ RecordWrite(ecx, 0, edx, ebx); |
437 __ ret(0); | 482 __ ret(0); |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 | 1028 |
984 // Do tail-call to runtime routine. | 1029 // Do tail-call to runtime routine. |
985 __ TailCallRuntime( | 1030 __ TailCallRuntime( |
986 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); | 1031 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); |
987 } | 1032 } |
988 | 1033 |
989 #undef __ | 1034 #undef __ |
990 | 1035 |
991 | 1036 |
992 } } // namespace v8::internal | 1037 } } // namespace v8::internal |
OLD | NEW |