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

Side by Side Diff: src/arm/full-codegen-arm.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, 4 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 | « no previous file | src/full-codegen.h » ('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 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 2614 matching lines...) Expand 10 before | Expand all | Expand 10 after
2625 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2625 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2626 2626
2627 VisitForControl(expr->expression(), if_true, if_false); 2627 VisitForControl(expr->expression(), if_true, if_false);
2628 2628
2629 Apply(context_, if_false, if_true); // Labels swapped. 2629 Apply(context_, if_false, if_true); // Labels swapped.
2630 break; 2630 break;
2631 } 2631 }
2632 2632
2633 case Token::TYPEOF: { 2633 case Token::TYPEOF: {
2634 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2634 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2635 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2635 VisitForTypeofValue(expr->expression(), kStack);
2636 if (proxy != NULL &&
2637 !proxy->var()->is_this() &&
2638 proxy->var()->is_global()) {
2639 Comment cmnt(masm_, "Global variable");
2640 __ ldr(r0, CodeGenerator::GlobalObject());
2641 __ mov(r2, Operand(proxy->name()));
2642 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2643 // Use a regular load, not a contextual load, to avoid a reference
2644 // error.
2645 __ Call(ic, RelocInfo::CODE_TARGET);
2646 __ push(r0);
2647 } else if (proxy != NULL &&
2648 proxy->var()->slot() != NULL &&
2649 proxy->var()->slot()->type() == Slot::LOOKUP) {
2650 __ mov(r0, Operand(proxy->name()));
2651 __ Push(cp, r0);
2652 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2653 __ push(r0);
2654 } else {
2655 // This expression cannot throw a reference error at the top level.
2656 VisitForValue(expr->expression(), kStack);
2657 }
2658
2659 __ CallRuntime(Runtime::kTypeof, 1); 2636 __ CallRuntime(Runtime::kTypeof, 1);
2660 Apply(context_, r0); 2637 Apply(context_, r0);
2661 break; 2638 break;
2662 } 2639 }
2663 2640
2664 case Token::ADD: { 2641 case Token::ADD: {
2665 Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2642 Comment cmt(masm_, "[ UnaryOperation (ADD)");
2666 VisitForValue(expr->expression(), kAccumulator); 2643 VisitForValue(expr->expression(), kAccumulator);
2667 Label no_conversion; 2644 Label no_conversion;
2668 __ tst(result_register(), Operand(kSmiTagMask)); 2645 __ tst(result_register(), Operand(kSmiTagMask));
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2869 } 2846 }
2870 } else { 2847 } else {
2871 Apply(context_, r0); 2848 Apply(context_, r0);
2872 } 2849 }
2873 break; 2850 break;
2874 } 2851 }
2875 } 2852 }
2876 } 2853 }
2877 2854
2878 2855
2879 void FullCodeGenerator::EmitNullCompare(bool strict, 2856 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) {
2880 Register obj, 2857 VariableProxy* proxy = expr->AsVariableProxy();
2881 Register null_const, 2858 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
2882 Label* if_true, 2859 Comment cmnt(masm_, "Global variable");
2883 Label* if_false, 2860 __ ldr(r0, CodeGenerator::GlobalObject());
2884 Register scratch) { 2861 __ mov(r2, Operand(proxy->name()));
2885 __ cmp(obj, null_const); 2862 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2886 if (strict) { 2863 // Use a regular load, not a contextual load, to avoid a reference
2887 Split(eq, if_true, if_false, NULL); 2864 // error.
2865 __ Call(ic, RelocInfo::CODE_TARGET);
2866 if (where == kStack) __ push(r0);
2867 } else if (proxy != NULL &&
2868 proxy->var()->slot() != NULL &&
2869 proxy->var()->slot()->type() == Slot::LOOKUP) {
2870 __ mov(r0, Operand(proxy->name()));
2871 __ Push(cp, r0);
2872 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2873 if (where == kStack) __ push(r0);
2888 } else { 2874 } else {
2889 __ b(eq, if_true); 2875 // This expression cannot throw a reference error at the top level.
2890 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 2876 VisitForValue(expr, where);
2891 __ cmp(obj, ip);
2892 __ b(eq, if_true);
2893 __ BranchOnSmi(obj, if_false);
2894 // It can be an undetectable object.
2895 __ ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
2896 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
2897 __ tst(scratch, Operand(1 << Map::kIsUndetectable));
2898 Split(ne, if_true, if_false, NULL);
2899 } 2877 }
2900 } 2878 }
2901 2879
2902 2880
2881 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
2882 Expression* left,
2883 Expression* right,
2884 Label* if_true,
2885 Label* if_false,
2886 Label* fall_through) {
2887 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
2888
2889 // Check for the pattern: typeof <expression> == <string literal>.
2890 Literal* right_literal = right->AsLiteral();
2891 if (right_literal == NULL) return false;
2892 Handle<Object> right_literal_value = right_literal->handle();
2893 if (!right_literal_value->IsString()) return false;
2894 UnaryOperation* left_unary = left->AsUnaryOperation();
2895 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
2896 Handle<String> check = Handle<String>::cast(right_literal_value);
2897
2898 VisitForTypeofValue(left_unary->expression(), kAccumulator);
2899 if (check->Equals(Heap::number_symbol())) {
2900 __ tst(r0, Operand(kSmiTagMask));
2901 __ b(eq, if_true);
2902 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
2903 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2904 __ cmp(r0, ip);
2905 Split(eq, if_true, if_false, fall_through);
2906 } else if (check->Equals(Heap::string_symbol())) {
2907 __ tst(r0, Operand(kSmiTagMask));
2908 __ b(eq, if_false);
2909 // Check for undetectable objects => false.
2910 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
2911 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
2912 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
2913 __ cmp(r1, Operand(1 << Map::kIsUndetectable));
2914 __ b(eq, if_false);
2915 __ ldrb(r1, FieldMemOperand(r0, Map::kInstanceTypeOffset));
2916 __ cmp(r1, Operand(FIRST_NONSTRING_TYPE));
2917 Split(lt, if_true, if_false, fall_through);
2918 } else if (check->Equals(Heap::boolean_symbol())) {
2919 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2920 __ cmp(r0, ip);
2921 __ b(eq, if_true);
2922 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
2923 __ cmp(r0, ip);
2924 Split(eq, if_true, if_false, fall_through);
2925 } else if (check->Equals(Heap::undefined_symbol())) {
2926 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
2927 __ cmp(r0, ip);
2928 __ b(eq, if_true);
2929 __ tst(r0, Operand(kSmiTagMask));
2930 __ b(eq, if_false);
2931 // Check for undetectable objects => true.
2932 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
2933 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
2934 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
2935 __ cmp(r1, Operand(1 << Map::kIsUndetectable));
2936 Split(eq, if_true, if_false, fall_through);
2937 } else if (check->Equals(Heap::function_symbol())) {
2938 __ tst(r0, Operand(kSmiTagMask));
2939 __ b(eq, if_false);
2940 __ CompareObjectType(r0, r1, r0, JS_FUNCTION_TYPE);
2941 __ b(eq, if_true);
2942 // Regular expressions => 'function' (they are callable).
2943 __ CompareInstanceType(r1, r0, JS_REGEXP_TYPE);
2944 Split(eq, if_true, if_false, fall_through);
2945 } else if (check->Equals(Heap::object_symbol())) {
2946 __ tst(r0, Operand(kSmiTagMask));
2947 __ b(eq, if_false);
2948 __ LoadRoot(ip, Heap::kNullValueRootIndex);
2949 __ cmp(r0, ip);
2950 __ b(eq, if_true);
2951 // Regular expressions => 'function', not 'object'.
2952 __ CompareObjectType(r0, r1, r0, JS_REGEXP_TYPE);
2953 __ b(eq, if_false);
2954 // Check for undetectable objects => false.
2955 __ ldrb(r0, FieldMemOperand(r1, Map::kBitFieldOffset));
2956 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
2957 __ cmp(r0, Operand(1 << Map::kIsUndetectable));
2958 __ b(eq, if_false);
2959 // Check for JS objects => true.
2960 __ ldrb(r0, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2961 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
2962 __ b(lt, if_false);
2963 __ cmp(r0, Operand(LAST_JS_OBJECT_TYPE));
2964 Split(le, if_true, if_false, fall_through);
2965 } else {
2966 if (if_false != fall_through) __ jmp(if_false);
2967 }
2968
2969 return true;
2970 }
2971
2972
2903 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2973 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2904 Comment cmnt(masm_, "[ CompareOperation"); 2974 Comment cmnt(masm_, "[ CompareOperation");
2905 2975
2906 // Always perform the comparison for its control flow. Pack the result 2976 // Always perform the comparison for its control flow. Pack the result
2907 // into the expression's context after the comparison is performed. 2977 // into the expression's context after the comparison is performed.
2908 2978
2909 Label materialize_true, materialize_false; 2979 Label materialize_true, materialize_false;
2910 Label* if_true = NULL; 2980 Label* if_true = NULL;
2911 Label* if_false = NULL; 2981 Label* if_false = NULL;
2912 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2982 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2913 2983
2984 // First we try a fast inlined version of the compare when one of
2985 // the operands is a literal.
2986 Token::Value op = expr->op();
2987 Expression* left = expr->left();
2988 Expression* right = expr->right();
2989 if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) {
2990 Apply(context_, if_true, if_false);
2991 return;
2992 }
2993
2914 VisitForValue(expr->left(), kStack); 2994 VisitForValue(expr->left(), kStack);
2915 switch (expr->op()) { 2995 switch (expr->op()) {
2916 case Token::IN: 2996 case Token::IN:
2917 VisitForValue(expr->right(), kStack); 2997 VisitForValue(expr->right(), kStack);
2918 __ InvokeBuiltin(Builtins::IN, CALL_JS); 2998 __ InvokeBuiltin(Builtins::IN, CALL_JS);
2919 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2999 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2920 __ cmp(r0, ip); 3000 __ cmp(r0, ip);
2921 Split(eq, if_true, if_false, NULL); 3001 Split(eq, if_true, if_false, NULL);
2922 break; 3002 break;
2923 3003
2924 case Token::INSTANCEOF: { 3004 case Token::INSTANCEOF: {
2925 VisitForValue(expr->right(), kStack); 3005 VisitForValue(expr->right(), kStack);
2926 InstanceofStub stub; 3006 InstanceofStub stub;
2927 __ CallStub(&stub); 3007 __ CallStub(&stub);
2928 // The stub returns 0 for true. 3008 // The stub returns 0 for true.
2929 __ tst(r0, r0); 3009 __ tst(r0, r0);
2930 Split(eq, if_true, if_false, NULL); 3010 Split(eq, if_true, if_false, NULL);
2931 break; 3011 break;
2932 } 3012 }
2933 3013
2934 default: { 3014 default: {
2935 VisitForValue(expr->right(), kAccumulator); 3015 VisitForValue(expr->right(), kAccumulator);
2936 Condition cc = eq; 3016 Condition cc = eq;
2937 bool strict = false; 3017 bool strict = false;
2938 switch (expr->op()) { 3018 switch (expr->op()) {
2939 case Token::EQ_STRICT: 3019 case Token::EQ_STRICT:
2940 strict = true; 3020 strict = true;
2941 // Fall through 3021 // Fall through
2942 case Token::EQ: { 3022 case Token::EQ:
2943 cc = eq; 3023 cc = eq;
2944 __ pop(r1); 3024 __ pop(r1);
2945 // If either operand is constant null we do a fast compare
2946 // against null.
2947 Literal* right_literal = expr->right()->AsLiteral();
2948 Literal* left_literal = expr->left()->AsLiteral();
2949 if (right_literal != NULL && right_literal->handle()->IsNull()) {
2950 EmitNullCompare(strict, r1, r0, if_true, if_false, r2);
2951 Apply(context_, if_true, if_false);
2952 return;
2953 } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
2954 EmitNullCompare(strict, r0, r1, if_true, if_false, r2);
2955 Apply(context_, if_true, if_false);
2956 return;
2957 }
2958 break; 3025 break;
2959 }
2960 case Token::LT: 3026 case Token::LT:
2961 cc = lt; 3027 cc = lt;
2962 __ pop(r1); 3028 __ pop(r1);
2963 break; 3029 break;
2964 case Token::GT: 3030 case Token::GT:
2965 // Reverse left and right sides to obtain ECMA-262 conversion order. 3031 // Reverse left and right sides to obtain ECMA-262 conversion order.
2966 cc = lt; 3032 cc = lt;
2967 __ mov(r1, result_register()); 3033 __ mov(r1, result_register());
2968 __ pop(r0); 3034 __ pop(r0);
2969 break; 3035 break;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3151 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
3086 __ add(pc, r1, Operand(masm_->CodeObject())); 3152 __ add(pc, r1, Operand(masm_->CodeObject()));
3087 } 3153 }
3088 3154
3089 3155
3090 #undef __ 3156 #undef __
3091 3157
3092 } } // namespace v8::internal 3158 } } // namespace v8::internal
3093 3159
3094 #endif // V8_TARGET_ARCH_ARM 3160 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/full-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698