Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 3110034: Optimize 'typeof <expr> == <string literal>' in the full codegen. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/full-codegen.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 2613 matching lines...) Expand 10 before | Expand all | Expand 10 after
2624 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2624 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2625 2625
2626 VisitForControl(expr->expression(), if_true, if_false); 2626 VisitForControl(expr->expression(), if_true, if_false);
2627 2627
2628 Apply(context_, if_false, if_true); // Labels swapped. 2628 Apply(context_, if_false, if_true); // Labels swapped.
2629 break; 2629 break;
2630 } 2630 }
2631 2631
2632 case Token::TYPEOF: { 2632 case Token::TYPEOF: {
2633 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2633 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2634 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2634 VisitForTypeofValue(expr->expression(), kStack);
2635 if (proxy != NULL &&
2636 !proxy->var()->is_this() &&
2637 proxy->var()->is_global()) {
2638 Comment cmnt(masm_, "Global variable");
2639 __ mov(eax, CodeGenerator::GlobalObject());
2640 __ mov(ecx, Immediate(proxy->name()));
2641 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2642 // Use a regular load, not a contextual load, to avoid a reference
2643 // error.
2644 __ call(ic, RelocInfo::CODE_TARGET);
2645 __ push(eax);
2646 } else if (proxy != NULL &&
2647 proxy->var()->slot() != NULL &&
2648 proxy->var()->slot()->type() == Slot::LOOKUP) {
2649 __ push(esi);
2650 __ push(Immediate(proxy->name()));
2651 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2652 __ push(eax);
2653 } else {
2654 // This expression cannot throw a reference error at the top level.
2655 VisitForValue(expr->expression(), kStack);
2656 }
2657
2658 __ CallRuntime(Runtime::kTypeof, 1); 2635 __ CallRuntime(Runtime::kTypeof, 1);
2659 Apply(context_, eax); 2636 Apply(context_, eax);
2660 break; 2637 break;
2661 } 2638 }
2662 2639
2663 case Token::ADD: { 2640 case Token::ADD: {
2664 Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2641 Comment cmt(masm_, "[ UnaryOperation (ADD)");
2665 VisitForValue(expr->expression(), kAccumulator); 2642 VisitForValue(expr->expression(), kAccumulator);
2666 Label no_conversion; 2643 Label no_conversion;
2667 __ test(result_register(), Immediate(kSmiTagMask)); 2644 __ test(result_register(), Immediate(kSmiTagMask));
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
2887 } 2864 }
2888 } else { 2865 } else {
2889 Apply(context_, eax); 2866 Apply(context_, eax);
2890 } 2867 }
2891 break; 2868 break;
2892 } 2869 }
2893 } 2870 }
2894 } 2871 }
2895 2872
2896 2873
2897 void FullCodeGenerator::EmitNullCompare(bool strict, 2874 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) {
2898 Register obj, 2875 VariableProxy* proxy = expr->AsVariableProxy();
2899 Register null_const, 2876 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
2900 Label* if_true, 2877 Comment cmnt(masm_, "Global variable");
2901 Label* if_false, 2878 __ mov(eax, CodeGenerator::GlobalObject());
2902 Register scratch) { 2879 __ mov(ecx, Immediate(proxy->name()));
2903 __ cmp(obj, Operand(null_const)); 2880 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2904 if (strict) { 2881 // Use a regular load, not a contextual load, to avoid a reference
2905 Split(equal, if_true, if_false, NULL); 2882 // error.
2883 __ call(ic, RelocInfo::CODE_TARGET);
2884 if (where == kStack) __ push(eax);
2885 } else if (proxy != NULL &&
2886 proxy->var()->slot() != NULL &&
2887 proxy->var()->slot()->type() == Slot::LOOKUP) {
2888 __ push(esi);
2889 __ push(Immediate(proxy->name()));
2890 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2891 if (where == kStack) __ push(eax);
2906 } else { 2892 } else {
2907 __ j(equal, if_true); 2893 // This expression cannot throw a reference error at the top level.
2908 __ cmp(obj, Factory::undefined_value()); 2894 VisitForValue(expr, where);
2909 __ j(equal, if_true);
2910 __ test(obj, Immediate(kSmiTagMask));
2911 __ j(zero, if_false);
2912 // It can be an undetectable object.
2913 __ mov(scratch, FieldOperand(obj, HeapObject::kMapOffset));
2914 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
2915 __ test(scratch, Immediate(1 << Map::kIsUndetectable));
2916 Split(not_zero, if_true, if_false, NULL);
2917 } 2895 }
2918 } 2896 }
2919 2897
2920 2898
2899 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
2900 Expression* left,
2901 Expression* right,
2902 Label* if_true,
2903 Label* if_false,
2904 Label* fall_through) {
2905 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
2906
2907 // Check for the pattern: typeof <expression> == <string literal>.
2908 Literal* right_literal = right->AsLiteral();
2909 if (right_literal == NULL) return false;
2910 Handle<Object> right_literal_value = right_literal->handle();
2911 if (!right_literal_value->IsString()) return false;
2912 UnaryOperation* left_unary = left->AsUnaryOperation();
2913 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
2914 Handle<String> check = Handle<String>::cast(right_literal_value);
2915
2916 VisitForTypeofValue(left_unary->expression(), kAccumulator);
2917 if (check->Equals(Heap::number_symbol())) {
2918 __ test(eax, Immediate(kSmiTagMask));
2919 __ j(zero, if_true);
2920 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
2921 Factory::heap_number_map());
2922 Split(equal, if_true, if_false, fall_through);
2923 } else if (check->Equals(Heap::string_symbol())) {
2924 __ test(eax, Immediate(kSmiTagMask));
2925 __ j(zero, if_false);
2926 // Check for undetectable objects => false.
2927 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
2928 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
2929 __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2930 __ j(not_zero, if_false);
2931 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
2932 Split(below, if_true, if_false, fall_through);
2933 } else if (check->Equals(Heap::boolean_symbol())) {
2934 __ cmp(eax, Factory::true_value());
2935 __ j(equal, if_true);
2936 __ cmp(eax, Factory::false_value());
2937 Split(equal, if_true, if_false, fall_through);
2938 } else if (check->Equals(Heap::undefined_symbol())) {
2939 __ cmp(eax, Factory::undefined_value());
2940 __ j(equal, if_true);
2941 __ test(eax, Immediate(kSmiTagMask));
2942 __ j(zero, if_false);
2943 // Check for undetectable objects => true.
2944 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
2945 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
2946 __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2947 Split(not_zero, if_true, if_false, fall_through);
2948 } else if (check->Equals(Heap::function_symbol())) {
2949 __ test(eax, Immediate(kSmiTagMask));
2950 __ j(zero, if_false);
2951 __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
2952 __ j(equal, if_true);
2953 // Regular expressions => 'function' (they are callable).
2954 __ CmpInstanceType(edx, JS_REGEXP_TYPE);
2955 Split(equal, if_true, if_false, fall_through);
2956 } else if (check->Equals(Heap::object_symbol())) {
2957 __ test(eax, Immediate(kSmiTagMask));
2958 __ j(zero, if_false);
2959 __ cmp(eax, Factory::null_value());
2960 __ j(equal, if_true);
2961 // Regular expressions => 'function', not 'object'.
2962 __ CmpObjectType(eax, JS_REGEXP_TYPE, edx);
2963 __ j(equal, if_false);
2964 // Check for undetectable objects => false.
2965 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
2966 __ test(ecx, Immediate(1 << Map::kIsUndetectable));
2967 __ j(not_zero, if_false);
2968 // Check for JS objects => true.
2969 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
2970 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
2971 __ j(less, if_false);
2972 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
2973 Split(less_equal, if_true, if_false, fall_through);
2974 } else {
2975 if (if_false != fall_through) __ jmp(if_false);
2976 }
2977
2978 return true;
2979 }
2980
2981
2921 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2982 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2922 Comment cmnt(masm_, "[ CompareOperation"); 2983 Comment cmnt(masm_, "[ CompareOperation");
2923 2984
2924 // Always perform the comparison for its control flow. Pack the result 2985 // Always perform the comparison for its control flow. Pack the result
2925 // into the expression's context after the comparison is performed. 2986 // into the expression's context after the comparison is performed.
2926 2987
2927 Label materialize_true, materialize_false; 2988 Label materialize_true, materialize_false;
2928 Label* if_true = NULL; 2989 Label* if_true = NULL;
2929 Label* if_false = NULL; 2990 Label* if_false = NULL;
2930 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2991 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2931 2992
2993 // First we try a fast inlined version of the compare when one of
2994 // the operands is a literal.
2995 Token::Value op = expr->op();
2996 Expression* left = expr->left();
2997 Expression* right = expr->right();
2998 if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) {
2999 Apply(context_, if_true, if_false);
3000 return;
3001 }
3002
2932 VisitForValue(expr->left(), kStack); 3003 VisitForValue(expr->left(), kStack);
2933 switch (expr->op()) { 3004 switch (expr->op()) {
2934 case Token::IN: 3005 case Token::IN:
2935 VisitForValue(expr->right(), kStack); 3006 VisitForValue(expr->right(), kStack);
2936 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3007 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
2937 __ cmp(eax, Factory::true_value()); 3008 __ cmp(eax, Factory::true_value());
2938 Split(equal, if_true, if_false, NULL); 3009 Split(equal, if_true, if_false, NULL);
2939 break; 3010 break;
2940 3011
2941 case Token::INSTANCEOF: { 3012 case Token::INSTANCEOF: {
2942 VisitForValue(expr->right(), kStack); 3013 VisitForValue(expr->right(), kStack);
2943 InstanceofStub stub; 3014 InstanceofStub stub;
2944 __ CallStub(&stub); 3015 __ CallStub(&stub);
2945 __ test(eax, Operand(eax)); 3016 __ test(eax, Operand(eax));
2946 // The stub returns 0 for true. 3017 // The stub returns 0 for true.
2947 Split(zero, if_true, if_false, NULL); 3018 Split(zero, if_true, if_false, NULL);
2948 break; 3019 break;
2949 } 3020 }
2950 3021
2951 default: { 3022 default: {
2952 VisitForValue(expr->right(), kAccumulator); 3023 VisitForValue(expr->right(), kAccumulator);
2953 Condition cc = no_condition; 3024 Condition cc = no_condition;
2954 bool strict = false; 3025 bool strict = false;
2955 switch (expr->op()) { 3026 switch (expr->op()) {
2956 case Token::EQ_STRICT: 3027 case Token::EQ_STRICT:
2957 strict = true; 3028 strict = true;
2958 // Fall through 3029 // Fall through
2959 case Token::EQ: { 3030 case Token::EQ:
2960 cc = equal; 3031 cc = equal;
2961 __ pop(edx); 3032 __ pop(edx);
2962 // If either operand is constant null we do a fast compare
2963 // against null.
2964 Literal* right_literal = expr->right()->AsLiteral();
2965 Literal* left_literal = expr->left()->AsLiteral();
2966 if (right_literal != NULL && right_literal->handle()->IsNull()) {
2967 EmitNullCompare(strict, edx, eax, if_true, if_false, ecx);
2968 Apply(context_, if_true, if_false);
2969 return;
2970 } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
2971 EmitNullCompare(strict, eax, edx, if_true, if_false, ecx);
2972 Apply(context_, if_true, if_false);
2973 return;
2974 }
2975 break; 3033 break;
2976 }
2977 case Token::LT: 3034 case Token::LT:
2978 cc = less; 3035 cc = less;
2979 __ pop(edx); 3036 __ pop(edx);
2980 break; 3037 break;
2981 case Token::GT: 3038 case Token::GT:
2982 // Reverse left and right sizes to obtain ECMA-262 conversion order. 3039 // Reverse left and right sizes to obtain ECMA-262 conversion order.
2983 cc = less; 3040 cc = less;
2984 __ mov(edx, result_register()); 3041 __ mov(edx, result_register());
2985 __ pop(eax); 3042 __ pop(eax);
2986 break; 3043 break;
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3103 // And return. 3160 // And return.
3104 __ ret(0); 3161 __ ret(0);
3105 } 3162 }
3106 3163
3107 3164
3108 #undef __ 3165 #undef __
3109 3166
3110 } } // namespace v8::internal 3167 } } // namespace v8::internal
3111 3168
3112 #endif // V8_TARGET_ARCH_IA32 3169 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/full-codegen.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698