OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 // ignore null and undefined in contrast to the specification; see | 867 // ignore null and undefined in contrast to the specification; see |
868 // ECMA-262 section 12.6.4. | 868 // ECMA-262 section 12.6.4. |
869 VisitForAccumulatorValue(stmt->enumerable()); | 869 VisitForAccumulatorValue(stmt->enumerable()); |
870 __ cmp(eax, isolate()->factory()->undefined_value()); | 870 __ cmp(eax, isolate()->factory()->undefined_value()); |
871 __ j(equal, &exit); | 871 __ j(equal, &exit); |
872 __ cmp(eax, isolate()->factory()->null_value()); | 872 __ cmp(eax, isolate()->factory()->null_value()); |
873 __ j(equal, &exit); | 873 __ j(equal, &exit); |
874 | 874 |
875 // Convert the object to a JS object. | 875 // Convert the object to a JS object. |
876 Label convert, done_convert; | 876 Label convert, done_convert; |
877 __ test(eax, Immediate(kSmiTagMask)); | 877 __ JumpIfSmi(eax, &convert, Label::kNear); |
878 __ j(zero, &convert, Label::kNear); | |
879 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 878 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
880 __ j(above_equal, &done_convert, Label::kNear); | 879 __ j(above_equal, &done_convert, Label::kNear); |
881 __ bind(&convert); | 880 __ bind(&convert); |
882 __ push(eax); | 881 __ push(eax); |
883 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 882 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
884 __ bind(&done_convert); | 883 __ bind(&done_convert); |
885 __ push(eax); | 884 __ push(eax); |
886 | 885 |
887 // Check cache validity in generated code. This is a fast case for | 886 // Check cache validity in generated code. This is a fast case for |
888 // the JSObject::IsSimpleEnum cache validity checks. If we cannot | 887 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
(...skipping 13 matching lines...) Expand all Loading... |
902 // check for an enum cache. Leave the map in ebx for the subsequent | 901 // check for an enum cache. Leave the map in ebx for the subsequent |
903 // prototype load. | 902 // prototype load. |
904 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); | 903 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); |
905 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOrBitField3Offset)); | 904 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOrBitField3Offset)); |
906 __ JumpIfSmi(edx, &call_runtime); | 905 __ JumpIfSmi(edx, &call_runtime); |
907 | 906 |
908 // Check that there is an enum cache in the non-empty instance | 907 // Check that there is an enum cache in the non-empty instance |
909 // descriptors (edx). This is the case if the next enumeration | 908 // descriptors (edx). This is the case if the next enumeration |
910 // index field does not contain a smi. | 909 // index field does not contain a smi. |
911 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); | 910 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); |
912 __ test(edx, Immediate(kSmiTagMask)); | 911 __ JumpIfSmi(edx, &call_runtime); |
913 __ j(zero, &call_runtime); | |
914 | 912 |
915 // For all objects but the receiver, check that the cache is empty. | 913 // For all objects but the receiver, check that the cache is empty. |
916 Label check_prototype; | 914 Label check_prototype; |
917 __ cmp(ecx, Operand(eax)); | 915 __ cmp(ecx, Operand(eax)); |
918 __ j(equal, &check_prototype, Label::kNear); | 916 __ j(equal, &check_prototype, Label::kNear); |
919 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 917 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
920 __ cmp(edx, isolate()->factory()->empty_fixed_array()); | 918 __ cmp(edx, isolate()->factory()->empty_fixed_array()); |
921 __ j(not_equal, &call_runtime); | 919 __ j(not_equal, &call_runtime); |
922 | 920 |
923 // Load the prototype from the map and loop if non-null. | 921 // Load the prototype from the map and loop if non-null. |
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2379 | 2377 |
2380 VisitForAccumulatorValue(args->at(0)); | 2378 VisitForAccumulatorValue(args->at(0)); |
2381 | 2379 |
2382 Label materialize_true, materialize_false; | 2380 Label materialize_true, materialize_false; |
2383 Label* if_true = NULL; | 2381 Label* if_true = NULL; |
2384 Label* if_false = NULL; | 2382 Label* if_false = NULL; |
2385 Label* fall_through = NULL; | 2383 Label* fall_through = NULL; |
2386 context()->PrepareTest(&materialize_true, &materialize_false, | 2384 context()->PrepareTest(&materialize_true, &materialize_false, |
2387 &if_true, &if_false, &fall_through); | 2385 &if_true, &if_false, &fall_through); |
2388 | 2386 |
2389 __ test(eax, Immediate(kSmiTagMask)); | 2387 __ JumpIfSmi(eax, if_false); |
2390 __ j(zero, if_false); | |
2391 __ cmp(eax, isolate()->factory()->null_value()); | 2388 __ cmp(eax, isolate()->factory()->null_value()); |
2392 __ j(equal, if_true); | 2389 __ j(equal, if_true); |
2393 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2390 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2394 // Undetectable objects behave like undefined when tested with typeof. | 2391 // Undetectable objects behave like undefined when tested with typeof. |
2395 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); | 2392 __ movzx_b(ecx, FieldOperand(ebx, Map::kBitFieldOffset)); |
2396 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); | 2393 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); |
2397 __ j(not_zero, if_false); | 2394 __ j(not_zero, if_false); |
2398 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 2395 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
2399 __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 2396 __ cmp(ecx, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
2400 __ j(below, if_false); | 2397 __ j(below, if_false); |
(...skipping 10 matching lines...) Expand all Loading... |
2411 | 2408 |
2412 VisitForAccumulatorValue(args->at(0)); | 2409 VisitForAccumulatorValue(args->at(0)); |
2413 | 2410 |
2414 Label materialize_true, materialize_false; | 2411 Label materialize_true, materialize_false; |
2415 Label* if_true = NULL; | 2412 Label* if_true = NULL; |
2416 Label* if_false = NULL; | 2413 Label* if_false = NULL; |
2417 Label* fall_through = NULL; | 2414 Label* fall_through = NULL; |
2418 context()->PrepareTest(&materialize_true, &materialize_false, | 2415 context()->PrepareTest(&materialize_true, &materialize_false, |
2419 &if_true, &if_false, &fall_through); | 2416 &if_true, &if_false, &fall_through); |
2420 | 2417 |
2421 __ test(eax, Immediate(kSmiTagMask)); | 2418 __ JumpIfSmi(eax, if_false); |
2422 __ j(equal, if_false); | |
2423 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); | 2419 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ebx); |
2424 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2420 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2425 Split(above_equal, if_true, if_false, fall_through); | 2421 Split(above_equal, if_true, if_false, fall_through); |
2426 | 2422 |
2427 context()->Plug(if_true, if_false); | 2423 context()->Plug(if_true, if_false); |
2428 } | 2424 } |
2429 | 2425 |
2430 | 2426 |
2431 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 2427 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
2432 ASSERT(args->length() == 1); | 2428 ASSERT(args->length() == 1); |
2433 | 2429 |
2434 VisitForAccumulatorValue(args->at(0)); | 2430 VisitForAccumulatorValue(args->at(0)); |
2435 | 2431 |
2436 Label materialize_true, materialize_false; | 2432 Label materialize_true, materialize_false; |
2437 Label* if_true = NULL; | 2433 Label* if_true = NULL; |
2438 Label* if_false = NULL; | 2434 Label* if_false = NULL; |
2439 Label* fall_through = NULL; | 2435 Label* fall_through = NULL; |
2440 context()->PrepareTest(&materialize_true, &materialize_false, | 2436 context()->PrepareTest(&materialize_true, &materialize_false, |
2441 &if_true, &if_false, &fall_through); | 2437 &if_true, &if_false, &fall_through); |
2442 | 2438 |
2443 __ test(eax, Immediate(kSmiTagMask)); | 2439 __ JumpIfSmi(eax, if_false); |
2444 __ j(zero, if_false); | |
2445 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2440 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2446 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); | 2441 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); |
2447 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); | 2442 __ test(ebx, Immediate(1 << Map::kIsUndetectable)); |
2448 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2443 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2449 Split(not_zero, if_true, if_false, fall_through); | 2444 Split(not_zero, if_true, if_false, fall_through); |
2450 | 2445 |
2451 context()->Plug(if_true, if_false); | 2446 context()->Plug(if_true, if_false); |
2452 } | 2447 } |
2453 | 2448 |
2454 | 2449 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 __ bind(&entry); | 2503 __ bind(&entry); |
2509 __ cmp(ebx, Operand(ecx)); | 2504 __ cmp(ebx, Operand(ecx)); |
2510 __ j(not_equal, &loop); | 2505 __ j(not_equal, &loop); |
2511 | 2506 |
2512 // Reload map as register ebx was used as temporary above. | 2507 // Reload map as register ebx was used as temporary above. |
2513 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2508 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2514 | 2509 |
2515 // If a valueOf property is not found on the object check that it's | 2510 // If a valueOf property is not found on the object check that it's |
2516 // prototype is the un-modified String prototype. If not result is false. | 2511 // prototype is the un-modified String prototype. If not result is false. |
2517 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); | 2512 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); |
2518 __ test(ecx, Immediate(kSmiTagMask)); | 2513 __ JumpIfSmi(ecx, if_false); |
2519 __ j(zero, if_false); | |
2520 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); | 2514 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); |
2521 __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2515 __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
2522 __ mov(edx, | 2516 __ mov(edx, |
2523 FieldOperand(edx, GlobalObject::kGlobalContextOffset)); | 2517 FieldOperand(edx, GlobalObject::kGlobalContextOffset)); |
2524 __ cmp(ecx, | 2518 __ cmp(ecx, |
2525 ContextOperand(edx, | 2519 ContextOperand(edx, |
2526 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 2520 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
2527 __ j(not_equal, if_false); | 2521 __ j(not_equal, if_false); |
2528 // Set the bit in the map to indicate that it has been checked safe for | 2522 // Set the bit in the map to indicate that it has been checked safe for |
2529 // default valueOf and set true result. | 2523 // default valueOf and set true result. |
(...skipping 11 matching lines...) Expand all Loading... |
2541 | 2535 |
2542 VisitForAccumulatorValue(args->at(0)); | 2536 VisitForAccumulatorValue(args->at(0)); |
2543 | 2537 |
2544 Label materialize_true, materialize_false; | 2538 Label materialize_true, materialize_false; |
2545 Label* if_true = NULL; | 2539 Label* if_true = NULL; |
2546 Label* if_false = NULL; | 2540 Label* if_false = NULL; |
2547 Label* fall_through = NULL; | 2541 Label* fall_through = NULL; |
2548 context()->PrepareTest(&materialize_true, &materialize_false, | 2542 context()->PrepareTest(&materialize_true, &materialize_false, |
2549 &if_true, &if_false, &fall_through); | 2543 &if_true, &if_false, &fall_through); |
2550 | 2544 |
2551 __ test(eax, Immediate(kSmiTagMask)); | 2545 __ JumpIfSmi(eax, if_false); |
2552 __ j(zero, if_false); | |
2553 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2546 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2554 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2547 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2555 Split(equal, if_true, if_false, fall_through); | 2548 Split(equal, if_true, if_false, fall_through); |
2556 | 2549 |
2557 context()->Plug(if_true, if_false); | 2550 context()->Plug(if_true, if_false); |
2558 } | 2551 } |
2559 | 2552 |
2560 | 2553 |
2561 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 2554 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
2562 ASSERT(args->length() == 1); | 2555 ASSERT(args->length() == 1); |
2563 | 2556 |
2564 VisitForAccumulatorValue(args->at(0)); | 2557 VisitForAccumulatorValue(args->at(0)); |
2565 | 2558 |
2566 Label materialize_true, materialize_false; | 2559 Label materialize_true, materialize_false; |
2567 Label* if_true = NULL; | 2560 Label* if_true = NULL; |
2568 Label* if_false = NULL; | 2561 Label* if_false = NULL; |
2569 Label* fall_through = NULL; | 2562 Label* fall_through = NULL; |
2570 context()->PrepareTest(&materialize_true, &materialize_false, | 2563 context()->PrepareTest(&materialize_true, &materialize_false, |
2571 &if_true, &if_false, &fall_through); | 2564 &if_true, &if_false, &fall_through); |
2572 | 2565 |
2573 __ test(eax, Immediate(kSmiTagMask)); | 2566 __ JumpIfSmi(eax, if_false); |
2574 __ j(equal, if_false); | |
2575 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | 2567 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
2576 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2568 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2577 Split(equal, if_true, if_false, fall_through); | 2569 Split(equal, if_true, if_false, fall_through); |
2578 | 2570 |
2579 context()->Plug(if_true, if_false); | 2571 context()->Plug(if_true, if_false); |
2580 } | 2572 } |
2581 | 2573 |
2582 | 2574 |
2583 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 2575 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
2584 ASSERT(args->length() == 1); | 2576 ASSERT(args->length() == 1); |
2585 | 2577 |
2586 VisitForAccumulatorValue(args->at(0)); | 2578 VisitForAccumulatorValue(args->at(0)); |
2587 | 2579 |
2588 Label materialize_true, materialize_false; | 2580 Label materialize_true, materialize_false; |
2589 Label* if_true = NULL; | 2581 Label* if_true = NULL; |
2590 Label* if_false = NULL; | 2582 Label* if_false = NULL; |
2591 Label* fall_through = NULL; | 2583 Label* fall_through = NULL; |
2592 context()->PrepareTest(&materialize_true, &materialize_false, | 2584 context()->PrepareTest(&materialize_true, &materialize_false, |
2593 &if_true, &if_false, &fall_through); | 2585 &if_true, &if_false, &fall_through); |
2594 | 2586 |
2595 __ test(eax, Immediate(kSmiTagMask)); | 2587 __ JumpIfSmi(eax, if_false); |
2596 __ j(equal, if_false); | |
2597 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); | 2588 __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx); |
2598 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 2589 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
2599 Split(equal, if_true, if_false, fall_through); | 2590 Split(equal, if_true, if_false, fall_through); |
2600 | 2591 |
2601 context()->Plug(if_true, if_false); | 2592 context()->Plug(if_true, if_false); |
2602 } | 2593 } |
2603 | 2594 |
2604 | 2595 |
2605 | 2596 |
2606 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 2597 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2694 } | 2685 } |
2695 | 2686 |
2696 | 2687 |
2697 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { | 2688 void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { |
2698 ASSERT(args->length() == 1); | 2689 ASSERT(args->length() == 1); |
2699 Label done, null, function, non_function_constructor; | 2690 Label done, null, function, non_function_constructor; |
2700 | 2691 |
2701 VisitForAccumulatorValue(args->at(0)); | 2692 VisitForAccumulatorValue(args->at(0)); |
2702 | 2693 |
2703 // If the object is a smi, we return null. | 2694 // If the object is a smi, we return null. |
2704 __ test(eax, Immediate(kSmiTagMask)); | 2695 __ JumpIfSmi(eax, &null); |
2705 __ j(zero, &null); | |
2706 | 2696 |
2707 // Check that the object is a JS object but take special care of JS | 2697 // Check that the object is a JS object but take special care of JS |
2708 // functions to make sure they have 'Function' as their class. | 2698 // functions to make sure they have 'Function' as their class. |
2709 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax); | 2699 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, eax); |
2710 // Map is now in eax. | 2700 // Map is now in eax. |
2711 __ j(below, &null); | 2701 __ j(below, &null); |
2712 | 2702 |
2713 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and | 2703 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and |
2714 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after | 2704 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after |
2715 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. | 2705 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2848 } | 2838 } |
2849 | 2839 |
2850 | 2840 |
2851 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { | 2841 void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) { |
2852 ASSERT(args->length() == 1); | 2842 ASSERT(args->length() == 1); |
2853 | 2843 |
2854 VisitForAccumulatorValue(args->at(0)); // Load the object. | 2844 VisitForAccumulatorValue(args->at(0)); // Load the object. |
2855 | 2845 |
2856 Label done; | 2846 Label done; |
2857 // If the object is a smi return the object. | 2847 // If the object is a smi return the object. |
2858 __ test(eax, Immediate(kSmiTagMask)); | 2848 __ JumpIfSmi(eax, &done, Label::kNear); |
2859 __ j(zero, &done, Label::kNear); | |
2860 // If the object is not a value type, return the object. | 2849 // If the object is not a value type, return the object. |
2861 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); | 2850 __ CmpObjectType(eax, JS_VALUE_TYPE, ebx); |
2862 __ j(not_equal, &done, Label::kNear); | 2851 __ j(not_equal, &done, Label::kNear); |
2863 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); | 2852 __ mov(eax, FieldOperand(eax, JSValue::kValueOffset)); |
2864 | 2853 |
2865 __ bind(&done); | 2854 __ bind(&done); |
2866 context()->Plug(eax); | 2855 context()->Plug(eax); |
2867 } | 2856 } |
2868 | 2857 |
2869 | 2858 |
(...skipping 15 matching lines...) Expand all Loading... |
2885 | 2874 |
2886 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { | 2875 void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) { |
2887 ASSERT(args->length() == 2); | 2876 ASSERT(args->length() == 2); |
2888 | 2877 |
2889 VisitForStackValue(args->at(0)); // Load the object. | 2878 VisitForStackValue(args->at(0)); // Load the object. |
2890 VisitForAccumulatorValue(args->at(1)); // Load the value. | 2879 VisitForAccumulatorValue(args->at(1)); // Load the value. |
2891 __ pop(ebx); // eax = value. ebx = object. | 2880 __ pop(ebx); // eax = value. ebx = object. |
2892 | 2881 |
2893 Label done; | 2882 Label done; |
2894 // If the object is a smi, return the value. | 2883 // If the object is a smi, return the value. |
2895 __ test(ebx, Immediate(kSmiTagMask)); | 2884 __ JumpIfSmi(ebx, &done, Label::kNear); |
2896 __ j(zero, &done, Label::kNear); | |
2897 | 2885 |
2898 // If the object is not a value type, return the value. | 2886 // If the object is not a value type, return the value. |
2899 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); | 2887 __ CmpObjectType(ebx, JS_VALUE_TYPE, ecx); |
2900 __ j(not_equal, &done, Label::kNear); | 2888 __ j(not_equal, &done, Label::kNear); |
2901 | 2889 |
2902 // Store the value. | 2890 // Store the value. |
2903 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); | 2891 __ mov(FieldOperand(ebx, JSValue::kValueOffset), eax); |
2904 // Update the write barrier. Save the value as it will be | 2892 // Update the write barrier. Save the value as it will be |
2905 // overwritten by the write barrier code and is needed afterward. | 2893 // overwritten by the write barrier code and is needed afterward. |
2906 __ mov(edx, eax); | 2894 __ mov(edx, eax); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3160 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); | 3148 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); |
3161 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), | 3149 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), |
3162 Immediate(isolate()->factory()->fixed_array_map())); | 3150 Immediate(isolate()->factory()->fixed_array_map())); |
3163 __ j(not_equal, &slow_case); | 3151 __ j(not_equal, &slow_case); |
3164 | 3152 |
3165 // Check that both indices are smis. | 3153 // Check that both indices are smis. |
3166 __ mov(index_1, Operand(esp, 1 * kPointerSize)); | 3154 __ mov(index_1, Operand(esp, 1 * kPointerSize)); |
3167 __ mov(index_2, Operand(esp, 0)); | 3155 __ mov(index_2, Operand(esp, 0)); |
3168 __ mov(temp, index_1); | 3156 __ mov(temp, index_1); |
3169 __ or_(temp, Operand(index_2)); | 3157 __ or_(temp, Operand(index_2)); |
3170 __ test(temp, Immediate(kSmiTagMask)); | 3158 __ JumpIfNotSmi(temp, &slow_case); |
3171 __ j(not_zero, &slow_case); | |
3172 | 3159 |
3173 // Check that both indices are valid. | 3160 // Check that both indices are valid. |
3174 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset)); | 3161 __ mov(temp, FieldOperand(object, JSArray::kLengthOffset)); |
3175 __ cmp(temp, Operand(index_1)); | 3162 __ cmp(temp, Operand(index_1)); |
3176 __ j(below_equal, &slow_case); | 3163 __ j(below_equal, &slow_case); |
3177 __ cmp(temp, Operand(index_2)); | 3164 __ cmp(temp, Operand(index_2)); |
3178 __ j(below_equal, &slow_case); | 3165 __ j(below_equal, &slow_case); |
3179 | 3166 |
3180 // Bring addresses into index1 and index2. | 3167 // Bring addresses into index1 and index2. |
3181 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); | 3168 __ lea(index_1, CodeGenerator::FixedArrayElementOperand(elements, index_1)); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3266 VisitForStackValue(args->at(0)); | 3253 VisitForStackValue(args->at(0)); |
3267 VisitForAccumulatorValue(args->at(1)); | 3254 VisitForAccumulatorValue(args->at(1)); |
3268 __ pop(left); | 3255 __ pop(left); |
3269 | 3256 |
3270 Label done, fail, ok; | 3257 Label done, fail, ok; |
3271 __ cmp(left, Operand(right)); | 3258 __ cmp(left, Operand(right)); |
3272 __ j(equal, &ok); | 3259 __ j(equal, &ok); |
3273 // Fail if either is a non-HeapObject. | 3260 // Fail if either is a non-HeapObject. |
3274 __ mov(tmp, left); | 3261 __ mov(tmp, left); |
3275 __ and_(Operand(tmp), right); | 3262 __ and_(Operand(tmp), right); |
3276 __ test(Operand(tmp), Immediate(kSmiTagMask)); | 3263 __ JumpIfSmi(tmp, &fail); |
3277 __ j(zero, &fail); | |
3278 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset)); | 3264 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset)); |
3279 __ CmpInstanceType(tmp, JS_REGEXP_TYPE); | 3265 __ CmpInstanceType(tmp, JS_REGEXP_TYPE); |
3280 __ j(not_equal, &fail); | 3266 __ j(not_equal, &fail); |
3281 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); | 3267 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset)); |
3282 __ j(not_equal, &fail); | 3268 __ j(not_equal, &fail); |
3283 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); | 3269 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset)); |
3284 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); | 3270 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset)); |
3285 __ j(equal, &ok); | 3271 __ j(equal, &ok); |
3286 __ bind(&fail); | 3272 __ bind(&fail); |
3287 __ mov(eax, Immediate(isolate()->factory()->false_value())); | 3273 __ mov(eax, Immediate(isolate()->factory()->false_value())); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3359 Register array_length = edi; | 3345 Register array_length = edi; |
3360 Register result_pos = no_reg; // Will be edi. | 3346 Register result_pos = no_reg; // Will be edi. |
3361 | 3347 |
3362 // Separator operand is already pushed. | 3348 // Separator operand is already pushed. |
3363 Operand separator_operand = Operand(esp, 2 * kPointerSize); | 3349 Operand separator_operand = Operand(esp, 2 * kPointerSize); |
3364 Operand result_operand = Operand(esp, 1 * kPointerSize); | 3350 Operand result_operand = Operand(esp, 1 * kPointerSize); |
3365 Operand array_length_operand = Operand(esp, 0); | 3351 Operand array_length_operand = Operand(esp, 0); |
3366 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 3352 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
3367 __ cld(); | 3353 __ cld(); |
3368 // Check that the array is a JSArray | 3354 // Check that the array is a JSArray |
3369 __ test(array, Immediate(kSmiTagMask)); | 3355 __ JumpIfSmi(array, &bailout); |
3370 __ j(zero, &bailout); | |
3371 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); | 3356 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); |
3372 __ j(not_equal, &bailout); | 3357 __ j(not_equal, &bailout); |
3373 | 3358 |
3374 // Check that the array has fast elements. | 3359 // Check that the array has fast elements. |
3375 __ CheckFastElements(scratch, &bailout); | 3360 __ CheckFastElements(scratch, &bailout); |
3376 | 3361 |
3377 // If the array has length zero, return the empty string. | 3362 // If the array has length zero, return the empty string. |
3378 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset)); | 3363 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset)); |
3379 __ SmiUntag(array_length); | 3364 __ SmiUntag(array_length); |
3380 __ j(not_zero, &non_trivial_array); | 3365 __ j(not_zero, &non_trivial_array); |
(...skipping 20 matching lines...) Expand all Loading... |
3401 // scratch, string_length, elements. | 3386 // scratch, string_length, elements. |
3402 if (FLAG_debug_code) { | 3387 if (FLAG_debug_code) { |
3403 __ cmp(index, Operand(array_length)); | 3388 __ cmp(index, Operand(array_length)); |
3404 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin"); | 3389 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin"); |
3405 } | 3390 } |
3406 __ bind(&loop); | 3391 __ bind(&loop); |
3407 __ mov(string, FieldOperand(elements, | 3392 __ mov(string, FieldOperand(elements, |
3408 index, | 3393 index, |
3409 times_pointer_size, | 3394 times_pointer_size, |
3410 FixedArray::kHeaderSize)); | 3395 FixedArray::kHeaderSize)); |
3411 __ test(string, Immediate(kSmiTagMask)); | 3396 __ JumpIfSmi(string, &bailout); |
3412 __ j(zero, &bailout); | |
3413 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); | 3397 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); |
3414 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3398 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
3415 __ and_(scratch, Immediate( | 3399 __ and_(scratch, Immediate( |
3416 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3400 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); |
3417 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | 3401 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); |
3418 __ j(not_equal, &bailout); | 3402 __ j(not_equal, &bailout); |
3419 __ add(string_length, | 3403 __ add(string_length, |
3420 FieldOperand(string, SeqAsciiString::kLengthOffset)); | 3404 FieldOperand(string, SeqAsciiString::kLengthOffset)); |
3421 __ j(overflow, &bailout); | 3405 __ j(overflow, &bailout); |
3422 __ add(Operand(index), Immediate(1)); | 3406 __ add(Operand(index), Immediate(1)); |
(...skipping 12 matching lines...) Expand all Loading... |
3435 // End of array_length live range. | 3419 // End of array_length live range. |
3436 result_pos = array_length; | 3420 result_pos = array_length; |
3437 array_length = no_reg; | 3421 array_length = no_reg; |
3438 | 3422 |
3439 // Live registers: | 3423 // Live registers: |
3440 // string_length: Sum of string lengths, as a smi. | 3424 // string_length: Sum of string lengths, as a smi. |
3441 // elements: FixedArray of strings. | 3425 // elements: FixedArray of strings. |
3442 | 3426 |
3443 // Check that the separator is a flat ASCII string. | 3427 // Check that the separator is a flat ASCII string. |
3444 __ mov(string, separator_operand); | 3428 __ mov(string, separator_operand); |
3445 __ test(string, Immediate(kSmiTagMask)); | 3429 __ JumpIfSmi(string, &bailout); |
3446 __ j(zero, &bailout); | |
3447 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); | 3430 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); |
3448 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3431 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
3449 __ and_(scratch, Immediate( | 3432 __ and_(scratch, Immediate( |
3450 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3433 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); |
3451 __ cmp(scratch, ASCII_STRING_TYPE); | 3434 __ cmp(scratch, ASCII_STRING_TYPE); |
3452 __ j(not_equal, &bailout); | 3435 __ j(not_equal, &bailout); |
3453 | 3436 |
3454 // Add (separator length times array_length) - separator length | 3437 // Add (separator length times array_length) - separator length |
3455 // to string_length. | 3438 // to string_length. |
3456 __ mov(scratch, separator_operand); | 3439 __ mov(scratch, separator_operand); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3728 } | 3711 } |
3729 __ CallRuntime(Runtime::kTypeof, 1); | 3712 __ CallRuntime(Runtime::kTypeof, 1); |
3730 context()->Plug(eax); | 3713 context()->Plug(eax); |
3731 break; | 3714 break; |
3732 } | 3715 } |
3733 | 3716 |
3734 case Token::ADD: { | 3717 case Token::ADD: { |
3735 Comment cmt(masm_, "[ UnaryOperation (ADD)"); | 3718 Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
3736 VisitForAccumulatorValue(expr->expression()); | 3719 VisitForAccumulatorValue(expr->expression()); |
3737 Label no_conversion; | 3720 Label no_conversion; |
3738 __ test(result_register(), Immediate(kSmiTagMask)); | 3721 __ JumpIfSmi(result_register(), &no_conversion); |
3739 __ j(zero, &no_conversion); | |
3740 ToNumberStub convert_stub; | 3722 ToNumberStub convert_stub; |
3741 __ CallStub(&convert_stub); | 3723 __ CallStub(&convert_stub); |
3742 __ bind(&no_conversion); | 3724 __ bind(&no_conversion); |
3743 context()->Plug(result_register()); | 3725 context()->Plug(result_register()); |
3744 break; | 3726 break; |
3745 } | 3727 } |
3746 | 3728 |
3747 case Token::SUB: | 3729 case Token::SUB: |
3748 EmitUnaryOperation(expr, "[ UnaryOperation (SUB)"); | 3730 EmitUnaryOperation(expr, "[ UnaryOperation (SUB)"); |
3749 break; | 3731 break; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3834 // in case evaluating the property load my have a side effect. | 3816 // in case evaluating the property load my have a side effect. |
3835 if (assign_type == VARIABLE) { | 3817 if (assign_type == VARIABLE) { |
3836 PrepareForBailout(expr->expression(), TOS_REG); | 3818 PrepareForBailout(expr->expression(), TOS_REG); |
3837 } else { | 3819 } else { |
3838 PrepareForBailoutForId(expr->CountId(), TOS_REG); | 3820 PrepareForBailoutForId(expr->CountId(), TOS_REG); |
3839 } | 3821 } |
3840 | 3822 |
3841 // Call ToNumber only if operand is not a smi. | 3823 // Call ToNumber only if operand is not a smi. |
3842 Label no_conversion; | 3824 Label no_conversion; |
3843 if (ShouldInlineSmiCase(expr->op())) { | 3825 if (ShouldInlineSmiCase(expr->op())) { |
3844 __ test(eax, Immediate(kSmiTagMask)); | 3826 __ JumpIfSmi(eax, &no_conversion, Label::kNear); |
3845 __ j(zero, &no_conversion, Label::kNear); | |
3846 } | 3827 } |
3847 ToNumberStub convert_stub; | 3828 ToNumberStub convert_stub; |
3848 __ CallStub(&convert_stub); | 3829 __ CallStub(&convert_stub); |
3849 __ bind(&no_conversion); | 3830 __ bind(&no_conversion); |
3850 | 3831 |
3851 // Save result for postfix expressions. | 3832 // Save result for postfix expressions. |
3852 if (expr->is_postfix()) { | 3833 if (expr->is_postfix()) { |
3853 if (!context()->IsEffect()) { | 3834 if (!context()->IsEffect()) { |
3854 // Save the result on the stack. If we have a named or keyed property | 3835 // Save the result on the stack. If we have a named or keyed property |
3855 // we store the result under the receiver that is currently on top | 3836 // we store the result under the receiver that is currently on top |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4201 VisitForAccumulatorValue(expr->expression()); | 4182 VisitForAccumulatorValue(expr->expression()); |
4202 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4183 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4203 | 4184 |
4204 __ cmp(eax, isolate()->factory()->null_value()); | 4185 __ cmp(eax, isolate()->factory()->null_value()); |
4205 if (expr->is_strict()) { | 4186 if (expr->is_strict()) { |
4206 Split(equal, if_true, if_false, fall_through); | 4187 Split(equal, if_true, if_false, fall_through); |
4207 } else { | 4188 } else { |
4208 __ j(equal, if_true); | 4189 __ j(equal, if_true); |
4209 __ cmp(eax, isolate()->factory()->undefined_value()); | 4190 __ cmp(eax, isolate()->factory()->undefined_value()); |
4210 __ j(equal, if_true); | 4191 __ j(equal, if_true); |
4211 __ test(eax, Immediate(kSmiTagMask)); | 4192 __ JumpIfSmi(eax, if_false); |
4212 __ j(zero, if_false); | |
4213 // It can be an undetectable object. | 4193 // It can be an undetectable object. |
4214 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 4194 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
4215 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); | 4195 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); |
4216 __ test(edx, Immediate(1 << Map::kIsUndetectable)); | 4196 __ test(edx, Immediate(1 << Map::kIsUndetectable)); |
4217 Split(not_zero, if_true, if_false, fall_through); | 4197 Split(not_zero, if_true, if_false, fall_through); |
4218 } | 4198 } |
4219 context()->Plug(if_true, if_false); | 4199 context()->Plug(if_true, if_false); |
4220 } | 4200 } |
4221 | 4201 |
4222 | 4202 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4328 // And return. | 4308 // And return. |
4329 __ ret(0); | 4309 __ ret(0); |
4330 } | 4310 } |
4331 | 4311 |
4332 | 4312 |
4333 #undef __ | 4313 #undef __ |
4334 | 4314 |
4335 } } // namespace v8::internal | 4315 } } // namespace v8::internal |
4336 | 4316 |
4337 #endif // V8_TARGET_ARCH_IA32 | 4317 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |