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

Side by Side Diff: src/x64/full-codegen-x64.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 | « src/ia32/full-codegen-ia32.cc ('k') | no next file » | 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 2609 matching lines...) Expand 10 before | Expand all | Expand 10 after
2620 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); 2620 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true);
2621 2621
2622 VisitForControl(expr->expression(), if_true, if_false); 2622 VisitForControl(expr->expression(), if_true, if_false);
2623 2623
2624 Apply(context_, if_false, if_true); // Labels swapped. 2624 Apply(context_, if_false, if_true); // Labels swapped.
2625 break; 2625 break;
2626 } 2626 }
2627 2627
2628 case Token::TYPEOF: { 2628 case Token::TYPEOF: {
2629 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2629 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2630 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2630 VisitForTypeofValue(expr->expression(), kStack);
2631 if (proxy != NULL &&
2632 !proxy->var()->is_this() &&
2633 proxy->var()->is_global()) {
2634 Comment cmnt(masm_, "Global variable");
2635 __ Move(rcx, proxy->name());
2636 __ movq(rax, CodeGenerator::GlobalObject());
2637 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2638 // Use a regular load, not a contextual load, to avoid a reference
2639 // error.
2640 __ Call(ic, RelocInfo::CODE_TARGET);
2641 __ push(rax);
2642 } else if (proxy != NULL &&
2643 proxy->var()->slot() != NULL &&
2644 proxy->var()->slot()->type() == Slot::LOOKUP) {
2645 __ push(rsi);
2646 __ Push(proxy->name());
2647 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2648 __ push(rax);
2649 } else {
2650 // This expression cannot throw a reference error at the top level.
2651 VisitForValue(expr->expression(), kStack);
2652 }
2653
2654 __ CallRuntime(Runtime::kTypeof, 1); 2631 __ CallRuntime(Runtime::kTypeof, 1);
2655 Apply(context_, rax); 2632 Apply(context_, rax);
2656 break; 2633 break;
2657 } 2634 }
2658 2635
2659 case Token::ADD: { 2636 case Token::ADD: {
2660 Comment cmt(masm_, "[ UnaryOperation (ADD)"); 2637 Comment cmt(masm_, "[ UnaryOperation (ADD)");
2661 VisitForValue(expr->expression(), kAccumulator); 2638 VisitForValue(expr->expression(), kAccumulator);
2662 Label no_conversion; 2639 Label no_conversion;
2663 Condition is_smi = masm_->CheckSmi(result_register()); 2640 Condition is_smi = masm_->CheckSmi(result_register());
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2881 } 2858 }
2882 } else { 2859 } else {
2883 Apply(context_, rax); 2860 Apply(context_, rax);
2884 } 2861 }
2885 break; 2862 break;
2886 } 2863 }
2887 } 2864 }
2888 } 2865 }
2889 2866
2890 2867
2891 void FullCodeGenerator::EmitNullCompare(bool strict, 2868 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) {
2892 Register obj, 2869 VariableProxy* proxy = expr->AsVariableProxy();
2893 Register null_const, 2870 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
2894 Label* if_true, 2871 Comment cmnt(masm_, "Global variable");
2895 Label* if_false, 2872 __ Move(rcx, proxy->name());
2896 Register scratch) { 2873 __ movq(rax, CodeGenerator::GlobalObject());
2897 __ cmpq(obj, null_const); 2874 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2898 if (strict) { 2875 // Use a regular load, not a contextual load, to avoid a reference
2899 Split(equal, if_true, if_false, NULL); 2876 // error.
2877 __ Call(ic, RelocInfo::CODE_TARGET);
2878 if (where == kStack) __ push(rax);
2879 } else if (proxy != NULL &&
2880 proxy->var()->slot() != NULL &&
2881 proxy->var()->slot()->type() == Slot::LOOKUP) {
2882 __ push(rsi);
2883 __ Push(proxy->name());
2884 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2885 if (where == kStack) __ push(rax);
2900 } else { 2886 } else {
2901 __ j(equal, if_true); 2887 // This expression cannot throw a reference error at the top level.
2902 __ CompareRoot(obj, Heap::kUndefinedValueRootIndex); 2888 VisitForValue(expr, where);
2903 __ j(equal, if_true);
2904 __ JumpIfSmi(obj, if_false);
2905 // It can be an undetectable object.
2906 __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset));
2907 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
2908 Immediate(1 << Map::kIsUndetectable));
2909 Split(not_zero, if_true, if_false, NULL);
2910 } 2889 }
2911 } 2890 }
2912 2891
2913 2892
2893 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
2894 Expression* left,
2895 Expression* right,
2896 Label* if_true,
2897 Label* if_false,
2898 Label* fall_through) {
2899 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
2900
2901 // Check for the pattern: typeof <expression> == <string literal>.
2902 Literal* right_literal = right->AsLiteral();
2903 if (right_literal == NULL) return false;
2904 Handle<Object> right_literal_value = right_literal->handle();
2905 if (!right_literal_value->IsString()) return false;
2906 UnaryOperation* left_unary = left->AsUnaryOperation();
2907 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
2908 Handle<String> check = Handle<String>::cast(right_literal_value);
2909
2910 VisitForTypeofValue(left_unary->expression(), kAccumulator);
2911 if (check->Equals(Heap::number_symbol())) {
2912 Condition is_smi = masm_->CheckSmi(rax);
2913 __ j(is_smi, if_true);
2914 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
2915 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
2916 Split(equal, if_true, if_false, fall_through);
2917 } else if (check->Equals(Heap::string_symbol())) {
2918 Condition is_smi = masm_->CheckSmi(rax);
2919 __ j(is_smi, if_false);
2920 // Check for undetectable objects => false.
2921 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
2922 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
2923 Immediate(1 << Map::kIsUndetectable));
2924 __ j(not_zero, if_false);
2925 __ CmpInstanceType(rdx, FIRST_NONSTRING_TYPE);
2926 Split(below, if_true, if_false, fall_through);
2927 } else if (check->Equals(Heap::boolean_symbol())) {
2928 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
2929 __ j(equal, if_true);
2930 __ CompareRoot(rax, Heap::kFalseValueRootIndex);
2931 Split(equal, if_true, if_false, fall_through);
2932 } else if (check->Equals(Heap::undefined_symbol())) {
2933 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
2934 __ j(equal, if_true);
2935 Condition is_smi = masm_->CheckSmi(rax);
2936 __ j(is_smi, if_false);
2937 // Check for undetectable objects => true.
2938 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
2939 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
2940 Immediate(1 << Map::kIsUndetectable));
2941 Split(not_zero, if_true, if_false, fall_through);
2942 } else if (check->Equals(Heap::function_symbol())) {
2943 Condition is_smi = masm_->CheckSmi(rax);
2944 __ j(is_smi, if_false);
2945 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
2946 __ j(equal, if_true);
2947 // Regular expressions => 'function' (they are callable).
2948 __ CmpInstanceType(rdx, JS_REGEXP_TYPE);
2949 Split(equal, if_true, if_false, fall_through);
2950 } else if (check->Equals(Heap::object_symbol())) {
2951 Condition is_smi = masm_->CheckSmi(rax);
2952 __ j(is_smi, if_false);
2953 __ CompareRoot(rax, Heap::kNullValueRootIndex);
2954 __ j(equal, if_true);
2955 // Regular expressions => 'function', not 'object'.
2956 __ CmpObjectType(rax, JS_REGEXP_TYPE, rdx);
2957 __ j(equal, if_false);
2958 // Check for undetectable objects => false.
2959 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
2960 Immediate(1 << Map::kIsUndetectable));
2961 __ j(not_zero, if_false);
2962 // Check for JS objects => true.
2963 __ CmpInstanceType(rdx, FIRST_JS_OBJECT_TYPE);
2964 __ j(below, if_false);
2965 __ CmpInstanceType(rdx, LAST_JS_OBJECT_TYPE);
2966 Split(below_equal, if_true, if_false, fall_through);
2967 } else {
2968 if (if_false != fall_through) __ jmp(if_false);
2969 }
2970
2971 return true;
2972 }
2973
2974
2914 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2975 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2915 Comment cmnt(masm_, "[ CompareOperation"); 2976 Comment cmnt(masm_, "[ CompareOperation");
2916 2977
2917 // Always perform the comparison for its control flow. Pack the result 2978 // Always perform the comparison for its control flow. Pack the result
2918 // into the expression's context after the comparison is performed. 2979 // into the expression's context after the comparison is performed.
2919 Label materialize_true, materialize_false; 2980 Label materialize_true, materialize_false;
2920 Label* if_true = NULL; 2981 Label* if_true = NULL;
2921 Label* if_false = NULL; 2982 Label* if_false = NULL;
2922 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); 2983 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
2923 2984
2985 // First we try a fast inlined version of the compare when one of
2986 // the operands is a literal.
2987 Token::Value op = expr->op();
2988 Expression* left = expr->left();
2989 Expression* right = expr->right();
2990 if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) {
2991 Apply(context_, if_true, if_false);
2992 return;
2993 }
2994
2924 VisitForValue(expr->left(), kStack); 2995 VisitForValue(expr->left(), kStack);
2925 switch (expr->op()) { 2996 switch (expr->op()) {
2926 case Token::IN: 2997 case Token::IN:
2927 VisitForValue(expr->right(), kStack); 2998 VisitForValue(expr->right(), kStack);
2928 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 2999 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
2929 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3000 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
2930 Split(equal, if_true, if_false, NULL); 3001 Split(equal, if_true, if_false, NULL);
2931 break; 3002 break;
2932 3003
2933 case Token::INSTANCEOF: { 3004 case Token::INSTANCEOF: {
2934 VisitForValue(expr->right(), kStack); 3005 VisitForValue(expr->right(), kStack);
2935 InstanceofStub stub; 3006 InstanceofStub stub;
2936 __ CallStub(&stub); 3007 __ CallStub(&stub);
2937 __ testq(rax, rax); 3008 __ testq(rax, rax);
2938 // The stub returns 0 for true. 3009 // The stub returns 0 for true.
2939 Split(zero, if_true, if_false, NULL); 3010 Split(zero, if_true, if_false, NULL);
2940 break; 3011 break;
2941 } 3012 }
2942 3013
2943 default: { 3014 default: {
2944 VisitForValue(expr->right(), kAccumulator); 3015 VisitForValue(expr->right(), kAccumulator);
2945 Condition cc = no_condition; 3016 Condition cc = no_condition;
2946 bool strict = false; 3017 bool strict = false;
2947 switch (expr->op()) { 3018 switch (expr->op()) {
2948 case Token::EQ_STRICT: 3019 case Token::EQ_STRICT:
2949 strict = true; 3020 strict = true;
2950 // Fall through. 3021 // Fall through.
2951 case Token::EQ: { 3022 case Token::EQ:
2952 cc = equal; 3023 cc = equal;
2953 __ pop(rdx); 3024 __ pop(rdx);
2954 // If either operand is constant null we do a fast compare
2955 // against null.
2956 Literal* right_literal = expr->right()->AsLiteral();
2957 Literal* left_literal = expr->left()->AsLiteral();
2958 if (right_literal != NULL && right_literal->handle()->IsNull()) {
2959 EmitNullCompare(strict, rdx, rax, if_true, if_false, rcx);
2960 Apply(context_, if_true, if_false);
2961 return;
2962 } else if (left_literal != NULL && left_literal->handle()->IsNull()) {
2963 EmitNullCompare(strict, rax, rdx, if_true, if_false, rcx);
2964 Apply(context_, if_true, if_false);
2965 return;
2966 }
2967 break; 3025 break;
2968 }
2969 case Token::LT: 3026 case Token::LT:
2970 cc = less; 3027 cc = less;
2971 __ pop(rdx); 3028 __ pop(rdx);
2972 break; 3029 break;
2973 case Token::GT: 3030 case Token::GT:
2974 // Reverse left and right sizes to obtain ECMA-262 conversion order. 3031 // Reverse left and right sizes to obtain ECMA-262 conversion order.
2975 cc = less; 3032 cc = less;
2976 __ movq(rdx, result_register()); 3033 __ movq(rdx, result_register());
2977 __ pop(rax); 3034 __ pop(rax);
2978 break; 3035 break;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3097 __ ret(0); 3154 __ ret(0);
3098 } 3155 }
3099 3156
3100 3157
3101 #undef __ 3158 #undef __
3102 3159
3103 3160
3104 } } // namespace v8::internal 3161 } } // namespace v8::internal
3105 3162
3106 #endif // V8_TARGET_ARCH_X64 3163 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698