OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 // lr: return address | 303 // lr: return address |
304 // sp[0]: last argument | 304 // sp[0]: last argument |
305 // This function is used for both construct and normal calls of Array. The only | 305 // This function is used for both construct and normal calls of Array. The only |
306 // difference between handling a construct call and a normal call is that for a | 306 // difference between handling a construct call and a normal call is that for a |
307 // construct call the constructor function in r1 needs to be preserved for | 307 // construct call the constructor function in r1 needs to be preserved for |
308 // entering the generic code. In both cases argc in r0 needs to be preserved. | 308 // entering the generic code. In both cases argc in r0 needs to be preserved. |
309 // Both registers are preserved by this code so no need to differentiate between | 309 // Both registers are preserved by this code so no need to differentiate between |
310 // construct call and normal call. | 310 // construct call and normal call. |
311 static void ArrayNativeCode(MacroAssembler* masm, | 311 static void ArrayNativeCode(MacroAssembler* masm, |
312 Label* call_generic_code) { | 312 Label* call_generic_code) { |
| 313 Counters* counters = masm->isolate()->counters(); |
313 Label argc_one_or_more, argc_two_or_more; | 314 Label argc_one_or_more, argc_two_or_more; |
314 | 315 |
315 // Check for array construction with zero arguments or one. | 316 // Check for array construction with zero arguments or one. |
316 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 317 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
317 __ b(ne, &argc_one_or_more); | 318 __ b(ne, &argc_one_or_more); |
318 | 319 |
319 // Handle construction of an empty array. | 320 // Handle construction of an empty array. |
320 AllocateEmptyJSArray(masm, | 321 AllocateEmptyJSArray(masm, |
321 r1, | 322 r1, |
322 r2, | 323 r2, |
323 r3, | 324 r3, |
324 r4, | 325 r4, |
325 r5, | 326 r5, |
326 JSArray::kPreallocatedArrayElements, | 327 JSArray::kPreallocatedArrayElements, |
327 call_generic_code); | 328 call_generic_code); |
328 __ IncrementCounter(COUNTERS->array_function_native(), 1, r3, r4); | 329 __ IncrementCounter(counters->array_function_native(), 1, r3, r4); |
329 // Setup return value, remove receiver from stack and return. | 330 // Setup return value, remove receiver from stack and return. |
330 __ mov(r0, r2); | 331 __ mov(r0, r2); |
331 __ add(sp, sp, Operand(kPointerSize)); | 332 __ add(sp, sp, Operand(kPointerSize)); |
332 __ Jump(lr); | 333 __ Jump(lr); |
333 | 334 |
334 // Check for one argument. Bail out if argument is not smi or if it is | 335 // Check for one argument. Bail out if argument is not smi or if it is |
335 // negative. | 336 // negative. |
336 __ bind(&argc_one_or_more); | 337 __ bind(&argc_one_or_more); |
337 __ cmp(r0, Operand(1)); | 338 __ cmp(r0, Operand(1)); |
338 __ b(ne, &argc_two_or_more); | 339 __ b(ne, &argc_two_or_more); |
(...skipping 15 matching lines...) Expand all Loading... |
354 AllocateJSArray(masm, | 355 AllocateJSArray(masm, |
355 r1, | 356 r1, |
356 r2, | 357 r2, |
357 r3, | 358 r3, |
358 r4, | 359 r4, |
359 r5, | 360 r5, |
360 r6, | 361 r6, |
361 r7, | 362 r7, |
362 true, | 363 true, |
363 call_generic_code); | 364 call_generic_code); |
364 __ IncrementCounter(COUNTERS->array_function_native(), 1, r2, r4); | 365 __ IncrementCounter(counters->array_function_native(), 1, r2, r4); |
365 // Setup return value, remove receiver and argument from stack and return. | 366 // Setup return value, remove receiver and argument from stack and return. |
366 __ mov(r0, r3); | 367 __ mov(r0, r3); |
367 __ add(sp, sp, Operand(2 * kPointerSize)); | 368 __ add(sp, sp, Operand(2 * kPointerSize)); |
368 __ Jump(lr); | 369 __ Jump(lr); |
369 | 370 |
370 // Handle construction of an array from a list of arguments. | 371 // Handle construction of an array from a list of arguments. |
371 __ bind(&argc_two_or_more); | 372 __ bind(&argc_two_or_more); |
372 __ mov(r2, Operand(r0, LSL, kSmiTagSize)); // Convet argc to a smi. | 373 __ mov(r2, Operand(r0, LSL, kSmiTagSize)); // Convet argc to a smi. |
373 | 374 |
374 // r0: argc | 375 // r0: argc |
375 // r1: constructor | 376 // r1: constructor |
376 // r2: array_size (smi) | 377 // r2: array_size (smi) |
377 // sp[0]: last argument | 378 // sp[0]: last argument |
378 AllocateJSArray(masm, | 379 AllocateJSArray(masm, |
379 r1, | 380 r1, |
380 r2, | 381 r2, |
381 r3, | 382 r3, |
382 r4, | 383 r4, |
383 r5, | 384 r5, |
384 r6, | 385 r6, |
385 r7, | 386 r7, |
386 false, | 387 false, |
387 call_generic_code); | 388 call_generic_code); |
388 __ IncrementCounter(COUNTERS->array_function_native(), 1, r2, r6); | 389 __ IncrementCounter(counters->array_function_native(), 1, r2, r6); |
389 | 390 |
390 // Fill arguments as array elements. Copy from the top of the stack (last | 391 // Fill arguments as array elements. Copy from the top of the stack (last |
391 // element) to the array backing store filling it backwards. Note: | 392 // element) to the array backing store filling it backwards. Note: |
392 // elements_array_end points after the backing store therefore PreIndex is | 393 // elements_array_end points after the backing store therefore PreIndex is |
393 // used when filling the backing store. | 394 // used when filling the backing store. |
394 // r0: argc | 395 // r0: argc |
395 // r3: JSArray | 396 // r3: JSArray |
396 // r4: elements_array storage start (untagged) | 397 // r4: elements_array storage start (untagged) |
397 // r5: elements_array_end (untagged) | 398 // r5: elements_array_end (untagged) |
398 // sp[0]: last argument | 399 // sp[0]: last argument |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 | 484 |
484 | 485 |
485 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 486 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
486 // ----------- S t a t e ------------- | 487 // ----------- S t a t e ------------- |
487 // -- r0 : number of arguments | 488 // -- r0 : number of arguments |
488 // -- r1 : constructor function | 489 // -- r1 : constructor function |
489 // -- lr : return address | 490 // -- lr : return address |
490 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) | 491 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) |
491 // -- sp[argc * 4] : receiver | 492 // -- sp[argc * 4] : receiver |
492 // ----------------------------------- | 493 // ----------------------------------- |
493 __ IncrementCounter(COUNTERS->string_ctor_calls(), 1, r2, r3); | 494 Counters* counters = masm->isolate()->counters(); |
| 495 __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3); |
494 | 496 |
495 Register function = r1; | 497 Register function = r1; |
496 if (FLAG_debug_code) { | 498 if (FLAG_debug_code) { |
497 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); | 499 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); |
498 __ cmp(function, Operand(r2)); | 500 __ cmp(function, Operand(r2)); |
499 __ Assert(eq, "Unexpected String function"); | 501 __ Assert(eq, "Unexpected String function"); |
500 } | 502 } |
501 | 503 |
502 // Load the first arguments in r0 and get rid of the rest. | 504 // Load the first arguments in r0 and get rid of the rest. |
503 Label no_arguments; | 505 Label no_arguments; |
504 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 506 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
505 __ b(eq, &no_arguments); | 507 __ b(eq, &no_arguments); |
506 // First args = sp[(argc - 1) * 4]. | 508 // First args = sp[(argc - 1) * 4]. |
507 __ sub(r0, r0, Operand(1)); | 509 __ sub(r0, r0, Operand(1)); |
508 __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); | 510 __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); |
509 // sp now point to args[0], drop args[0] + receiver. | 511 // sp now point to args[0], drop args[0] + receiver. |
510 __ Drop(2); | 512 __ Drop(2); |
511 | 513 |
512 Register argument = r2; | 514 Register argument = r2; |
513 Label not_cached, argument_is_string; | 515 Label not_cached, argument_is_string; |
514 NumberToStringStub::GenerateLookupNumberStringCache( | 516 NumberToStringStub::GenerateLookupNumberStringCache( |
515 masm, | 517 masm, |
516 r0, // Input. | 518 r0, // Input. |
517 argument, // Result. | 519 argument, // Result. |
518 r3, // Scratch. | 520 r3, // Scratch. |
519 r4, // Scratch. | 521 r4, // Scratch. |
520 r5, // Scratch. | 522 r5, // Scratch. |
521 false, // Is it a Smi? | 523 false, // Is it a Smi? |
522 ¬_cached); | 524 ¬_cached); |
523 __ IncrementCounter(COUNTERS->string_ctor_cached_number(), 1, r3, r4); | 525 __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4); |
524 __ bind(&argument_is_string); | 526 __ bind(&argument_is_string); |
525 | 527 |
526 // ----------- S t a t e ------------- | 528 // ----------- S t a t e ------------- |
527 // -- r2 : argument converted to string | 529 // -- r2 : argument converted to string |
528 // -- r1 : constructor function | 530 // -- r1 : constructor function |
529 // -- lr : return address | 531 // -- lr : return address |
530 // ----------------------------------- | 532 // ----------------------------------- |
531 | 533 |
532 Label gc_required; | 534 Label gc_required; |
533 __ AllocateInNewSpace(JSValue::kSize, | 535 __ AllocateInNewSpace(JSValue::kSize, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 __ bind(¬_cached); | 569 __ bind(¬_cached); |
568 __ JumpIfSmi(r0, &convert_argument); | 570 __ JumpIfSmi(r0, &convert_argument); |
569 | 571 |
570 // Is it a String? | 572 // Is it a String? |
571 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 573 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
572 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 574 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
573 ASSERT(kNotStringTag != 0); | 575 ASSERT(kNotStringTag != 0); |
574 __ tst(r3, Operand(kIsNotStringMask)); | 576 __ tst(r3, Operand(kIsNotStringMask)); |
575 __ b(ne, &convert_argument); | 577 __ b(ne, &convert_argument); |
576 __ mov(argument, r0); | 578 __ mov(argument, r0); |
577 __ IncrementCounter(COUNTERS->string_ctor_conversions(), 1, r3, r4); | 579 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); |
578 __ b(&argument_is_string); | 580 __ b(&argument_is_string); |
579 | 581 |
580 // Invoke the conversion builtin and put the result into r2. | 582 // Invoke the conversion builtin and put the result into r2. |
581 __ bind(&convert_argument); | 583 __ bind(&convert_argument); |
582 __ push(function); // Preserve the function. | 584 __ push(function); // Preserve the function. |
583 __ IncrementCounter(COUNTERS->string_ctor_conversions(), 1, r3, r4); | 585 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); |
584 __ EnterInternalFrame(); | 586 __ EnterInternalFrame(); |
585 __ push(r0); | 587 __ push(r0); |
586 __ InvokeBuiltin(Builtins::TO_STRING, CALL_JS); | 588 __ InvokeBuiltin(Builtins::TO_STRING, CALL_JS); |
587 __ LeaveInternalFrame(); | 589 __ LeaveInternalFrame(); |
588 __ pop(function); | 590 __ pop(function); |
589 __ mov(argument, r0); | 591 __ mov(argument, r0); |
590 __ b(&argument_is_string); | 592 __ b(&argument_is_string); |
591 | 593 |
592 // Load the empty string into r2, remove the receiver from the | 594 // Load the empty string into r2, remove the receiver from the |
593 // stack, and jump back to the case where the argument is a string. | 595 // stack, and jump back to the case where the argument is a string. |
594 __ bind(&no_arguments); | 596 __ bind(&no_arguments); |
595 __ LoadRoot(argument, Heap::kEmptyStringRootIndex); | 597 __ LoadRoot(argument, Heap::kEmptyStringRootIndex); |
596 __ Drop(1); | 598 __ Drop(1); |
597 __ b(&argument_is_string); | 599 __ b(&argument_is_string); |
598 | 600 |
599 // At this point the argument is already a string. Call runtime to | 601 // At this point the argument is already a string. Call runtime to |
600 // create a string wrapper. | 602 // create a string wrapper. |
601 __ bind(&gc_required); | 603 __ bind(&gc_required); |
602 __ IncrementCounter(COUNTERS->string_ctor_gc_required(), 1, r3, r4); | 604 __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); |
603 __ EnterInternalFrame(); | 605 __ EnterInternalFrame(); |
604 __ push(argument); | 606 __ push(argument); |
605 __ CallRuntime(Runtime::kNewStringWrapper, 1); | 607 __ CallRuntime(Runtime::kNewStringWrapper, 1); |
606 __ LeaveInternalFrame(); | 608 __ LeaveInternalFrame(); |
607 __ Ret(); | 609 __ Ret(); |
608 } | 610 } |
609 | 611 |
610 | 612 |
611 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { | 613 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
612 // ----------- S t a t e ------------- | 614 // ----------- S t a t e ------------- |
(...skipping 26 matching lines...) Expand all Loading... |
639 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); | 641 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); |
640 } | 642 } |
641 | 643 |
642 | 644 |
643 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 645 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
644 bool is_api_function, | 646 bool is_api_function, |
645 bool count_constructions) { | 647 bool count_constructions) { |
646 // Should never count constructions for api objects. | 648 // Should never count constructions for api objects. |
647 ASSERT(!is_api_function || !count_constructions); | 649 ASSERT(!is_api_function || !count_constructions); |
648 | 650 |
| 651 Isolate* isolate = masm->isolate(); |
| 652 |
649 // Enter a construct frame. | 653 // Enter a construct frame. |
650 __ EnterConstructFrame(); | 654 __ EnterConstructFrame(); |
651 | 655 |
652 // Preserve the two incoming parameters on the stack. | 656 // Preserve the two incoming parameters on the stack. |
653 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 657 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
654 __ push(r0); // Smi-tagged arguments count. | 658 __ push(r0); // Smi-tagged arguments count. |
655 __ push(r1); // Constructor function. | 659 __ push(r1); // Constructor function. |
656 | 660 |
657 // Try to allocate the object without transitioning into C code. If any of the | 661 // Try to allocate the object without transitioning into C code. If any of the |
658 // preconditions is not met, the code bails out to the runtime call. | 662 // preconditions is not met, the code bails out to the runtime call. |
659 Label rt_call, allocated; | 663 Label rt_call, allocated; |
660 if (FLAG_inline_new) { | 664 if (FLAG_inline_new) { |
661 Label undo_allocation; | 665 Label undo_allocation; |
662 #ifdef ENABLE_DEBUGGER_SUPPORT | 666 #ifdef ENABLE_DEBUGGER_SUPPORT |
663 ExternalReference debug_step_in_fp = | 667 ExternalReference debug_step_in_fp = |
664 ExternalReference::debug_step_in_fp_address(masm->isolate()); | 668 ExternalReference::debug_step_in_fp_address(isolate); |
665 __ mov(r2, Operand(debug_step_in_fp)); | 669 __ mov(r2, Operand(debug_step_in_fp)); |
666 __ ldr(r2, MemOperand(r2)); | 670 __ ldr(r2, MemOperand(r2)); |
667 __ tst(r2, r2); | 671 __ tst(r2, r2); |
668 __ b(ne, &rt_call); | 672 __ b(ne, &rt_call); |
669 #endif | 673 #endif |
670 | 674 |
671 // Load the initial map and verify that it is in fact a map. | 675 // Load the initial map and verify that it is in fact a map. |
672 // r1: constructor function | 676 // r1: constructor function |
673 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 677 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
674 __ tst(r2, Operand(kSmiTagMask)); | 678 __ tst(r2, Operand(kSmiTagMask)); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 __ bind(&entry); | 905 __ bind(&entry); |
902 __ sub(r3, r3, Operand(2), SetCC); | 906 __ sub(r3, r3, Operand(2), SetCC); |
903 __ b(ge, &loop); | 907 __ b(ge, &loop); |
904 | 908 |
905 // Call the function. | 909 // Call the function. |
906 // r0: number of arguments | 910 // r0: number of arguments |
907 // r1: constructor function | 911 // r1: constructor function |
908 if (is_api_function) { | 912 if (is_api_function) { |
909 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 913 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
910 Handle<Code> code = Handle<Code>( | 914 Handle<Code> code = Handle<Code>( |
911 masm->isolate()->builtins()->builtin( | 915 isolate->builtins()->builtin(Builtins::HandleApiCallConstruct)); |
912 Builtins::HandleApiCallConstruct)); | |
913 ParameterCount expected(0); | 916 ParameterCount expected(0); |
914 __ InvokeCode(code, expected, expected, | 917 __ InvokeCode(code, expected, expected, |
915 RelocInfo::CODE_TARGET, CALL_FUNCTION); | 918 RelocInfo::CODE_TARGET, CALL_FUNCTION); |
916 } else { | 919 } else { |
917 ParameterCount actual(r0); | 920 ParameterCount actual(r0); |
918 __ InvokeFunction(r1, actual, CALL_FUNCTION); | 921 __ InvokeFunction(r1, actual, CALL_FUNCTION); |
919 } | 922 } |
920 | 923 |
921 // Pop the function from the stack. | 924 // Pop the function from the stack. |
922 // sp[0]: constructor function | 925 // sp[0]: constructor function |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 // return. | 962 // return. |
960 __ bind(&exit); | 963 __ bind(&exit); |
961 // r0: result | 964 // r0: result |
962 // sp[0]: receiver (newly allocated object) | 965 // sp[0]: receiver (newly allocated object) |
963 // sp[1]: constructor function | 966 // sp[1]: constructor function |
964 // sp[2]: number of arguments (smi-tagged) | 967 // sp[2]: number of arguments (smi-tagged) |
965 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); | 968 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
966 __ LeaveConstructFrame(); | 969 __ LeaveConstructFrame(); |
967 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 970 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
968 __ add(sp, sp, Operand(kPointerSize)); | 971 __ add(sp, sp, Operand(kPointerSize)); |
969 __ IncrementCounter(COUNTERS->constructed_objects(), 1, r1, r2); | 972 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
970 __ Jump(lr); | 973 __ Jump(lr); |
971 } | 974 } |
972 | 975 |
973 | 976 |
974 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 977 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
975 Generate_JSConstructStubHelper(masm, false, true); | 978 Generate_JSConstructStubHelper(masm, false, true); |
976 } | 979 } |
977 | 980 |
978 | 981 |
979 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 982 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 __ bind(&dont_adapt_arguments); | 1623 __ bind(&dont_adapt_arguments); |
1621 __ Jump(r3); | 1624 __ Jump(r3); |
1622 } | 1625 } |
1623 | 1626 |
1624 | 1627 |
1625 #undef __ | 1628 #undef __ |
1626 | 1629 |
1627 } } // namespace v8::internal | 1630 } } // namespace v8::internal |
1628 | 1631 |
1629 #endif // V8_TARGET_ARCH_ARM | 1632 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |