| 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 |