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

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

Issue 27267: Experimental: periodic merge from the bleeding edge branch to the code... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 10 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/codegen-arm.cc ('k') | src/compilation-cache.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 3071 matching lines...) Expand 10 before | Expand all | Expand 10 after
3082 // If there was no control flow to slow, we can exit early. 3082 // If there was no control flow to slow, we can exit early.
3083 if (!slow.is_linked()) { 3083 if (!slow.is_linked()) {
3084 frame_->Push(&value); 3084 frame_->Push(&value);
3085 return; 3085 return;
3086 } 3086 }
3087 3087
3088 done.Jump(&value); 3088 done.Jump(&value);
3089 3089
3090 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 3090 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
3091 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); 3091 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
3092 // Allocate a fresh register to use as a temp in 3092 // Only generate the fast case for locals that rewrite to slots.
3093 // ContextSlotOperandCheckExtensions and to hold the result 3093 // This rules out argument loads.
3094 // value. 3094 if (potential_slot != NULL) {
3095 value = allocator_->Allocate(); 3095 // Allocate a fresh register to use as a temp in
3096 ASSERT(value.is_valid()); 3096 // ContextSlotOperandCheckExtensions and to hold the result
3097 __ mov(value.reg(), 3097 // value.
3098 ContextSlotOperandCheckExtensions(potential_slot, value, &slow)); 3098 value = allocator_->Allocate();
3099 // There is always control flow to slow from 3099 ASSERT(value.is_valid());
3100 // ContextSlotOperandCheckExtensions. 3100 __ mov(value.reg(),
3101 done.Jump(&value); 3101 ContextSlotOperandCheckExtensions(potential_slot,
3102 value,
3103 &slow));
3104 // There is always control flow to slow from
3105 // ContextSlotOperandCheckExtensions.
3106 done.Jump(&value);
3107 }
3102 } 3108 }
3103 3109
3104 slow.Bind(); 3110 slow.Bind();
3105 frame_->Push(esi); 3111 frame_->Push(esi);
3106 frame_->Push(slot->var()->name()); 3112 frame_->Push(slot->var()->name());
3107 if (typeof_state == INSIDE_TYPEOF) { 3113 if (typeof_state == INSIDE_TYPEOF) {
3108 value = 3114 value =
3109 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3115 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3110 } else { 3116 } else {
3111 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 3117 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3153 3159
3154 3160
3155 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( 3161 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
3156 Slot* slot, 3162 Slot* slot,
3157 TypeofState typeof_state, 3163 TypeofState typeof_state,
3158 JumpTarget* slow) { 3164 JumpTarget* slow) {
3159 // Check that no extension objects have been created by calls to 3165 // Check that no extension objects have been created by calls to
3160 // eval from the current scope to the global scope. 3166 // eval from the current scope to the global scope.
3161 Result context(esi, this); 3167 Result context(esi, this);
3162 Result tmp = allocator_->Allocate(); 3168 Result tmp = allocator_->Allocate();
3163 ASSERT(tmp.is_valid()); // Called with all non-reserved registers available. 3169 ASSERT(tmp.is_valid()); // All non-reserved registers were available.
3164 3170
3165 for (Scope* s = scope(); s != NULL; s = s->outer_scope()) { 3171 Scope* s = scope();
3172 while (s != NULL) {
3166 if (s->num_heap_slots() > 0) { 3173 if (s->num_heap_slots() > 0) {
3167 if (s->calls_eval()) { 3174 if (s->calls_eval()) {
3168 // Check that extension is NULL. 3175 // Check that extension is NULL.
3169 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX), 3176 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX),
3170 Immediate(0)); 3177 Immediate(0));
3171 slow->Branch(not_equal, not_taken); 3178 slow->Branch(not_equal, not_taken);
3172 } 3179 }
3173 // Load next context in chain. 3180 // Load next context in chain.
3174 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX)); 3181 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX));
3175 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); 3182 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
3176 context = tmp; 3183 context = tmp;
3177 } 3184 }
3178 // If no outer scope calls eval, we do not need to check more 3185 // If no outer scope calls eval, we do not need to check more
3179 // context extensions. 3186 // context extensions. If we have reached an eval scope, we check
3180 if (!s->outer_scope_calls_eval()) break; 3187 // all extensions from this point.
3188 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
3189 s = s->outer_scope();
3190 }
3191
3192 if (s->is_eval_scope()) {
3193 // Loop up the context chain. There is no frame effect so it is
3194 // safe to use raw labels here.
3195 Label next, fast;
3196 if (!context.reg().is(tmp.reg())) __ mov(tmp.reg(), context.reg());
3197 __ bind(&next);
3198 // Terminate at global context.
3199 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
3200 Immediate(Factory::global_context_map()));
3201 __ j(equal, &fast);
3202 // Check that extension is NULL.
3203 __ cmp(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0));
3204 slow->Branch(not_equal, not_taken);
3205 // Load next context in chain.
3206 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX));
3207 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
3208 __ jmp(&next);
3209 __ bind(&fast);
3181 } 3210 }
3182 context.Unuse(); 3211 context.Unuse();
3183 tmp.Unuse(); 3212 tmp.Unuse();
3184 3213
3185 // All extension objects were empty and it is safe to use a global 3214 // All extension objects were empty and it is safe to use a global
3186 // load IC call. 3215 // load IC call.
3187 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3216 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3188 // Load the global object. 3217 // Load the global object.
3189 LoadGlobal(); 3218 LoadGlobal();
3190 // Setup the name register. All non-reserved registers are available. 3219 // Setup the name register. All non-reserved registers are available.
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
3632 3661
3633 { Reference target(this, node->target()); 3662 { Reference target(this, node->target());
3634 if (target.is_illegal()) { 3663 if (target.is_illegal()) {
3635 // Fool the virtual frame into thinking that we left the assignment's 3664 // Fool the virtual frame into thinking that we left the assignment's
3636 // value on the frame. 3665 // value on the frame.
3637 frame_->Push(Smi::FromInt(0)); 3666 frame_->Push(Smi::FromInt(0));
3638 return; 3667 return;
3639 } 3668 }
3640 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 3669 Variable* var = node->target()->AsVariableProxy()->AsVariable();
3641 3670
3671 if (node->starts_initialization_block()) {
3672 ASSERT(target.type() == Reference::NAMED ||
3673 target.type() == Reference::KEYED);
3674 // Change to slow case in the beginning of an initialization
3675 // block to avoid the quadratic behavior of repeatedly adding
3676 // fast properties.
3677
3678 // The receiver is the argument to the runtime call. It is the
3679 // first value pushed when the reference was loaded to the
3680 // frame.
3681 frame_->PushElementAt(target.size() - 1);
3682 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1);
3683 }
3642 if (node->op() == Token::ASSIGN || 3684 if (node->op() == Token::ASSIGN ||
3643 node->op() == Token::INIT_VAR || 3685 node->op() == Token::INIT_VAR ||
3644 node->op() == Token::INIT_CONST) { 3686 node->op() == Token::INIT_CONST) {
3645 Load(node->value()); 3687 Load(node->value());
3688
3646 } else { 3689 } else {
3647 Literal* literal = node->value()->AsLiteral(); 3690 Literal* literal = node->value()->AsLiteral();
3648 Variable* right_var = node->value()->AsVariableProxy()->AsVariable(); 3691 Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
3649 // There are two cases where the target is not read in the right hand 3692 // There are two cases where the target is not read in the right hand
3650 // side, that are easy to test for: the right hand side is a literal, 3693 // side, that are easy to test for: the right hand side is a literal,
3651 // or the right hand side is a different variable. TakeValue invalidates 3694 // or the right hand side is a different variable. TakeValue invalidates
3652 // the target, with an implicit promise that it will be written to again 3695 // the target, with an implicit promise that it will be written to again
3653 // before it is read. 3696 // before it is read.
3654 if (literal != NULL || (right_var != NULL && right_var != var)) { 3697 if (literal != NULL || (right_var != NULL && right_var != var)) {
3655 target.TakeValue(NOT_INSIDE_TYPEOF); 3698 target.TakeValue(NOT_INSIDE_TYPEOF);
(...skipping 16 matching lines...) Expand all
3672 } else { 3715 } else {
3673 CodeForSourcePosition(node->position()); 3716 CodeForSourcePosition(node->position());
3674 if (node->op() == Token::INIT_CONST) { 3717 if (node->op() == Token::INIT_CONST) {
3675 // Dynamic constant initializations must use the function context 3718 // Dynamic constant initializations must use the function context
3676 // and initialize the actual constant declared. Dynamic variable 3719 // and initialize the actual constant declared. Dynamic variable
3677 // initializations are simply assignments and use SetValue. 3720 // initializations are simply assignments and use SetValue.
3678 target.SetValue(CONST_INIT); 3721 target.SetValue(CONST_INIT);
3679 } else { 3722 } else {
3680 target.SetValue(NOT_CONST_INIT); 3723 target.SetValue(NOT_CONST_INIT);
3681 } 3724 }
3725 if (node->ends_initialization_block()) {
3726 ASSERT(target.type() == Reference::NAMED ||
3727 target.type() == Reference::KEYED);
3728 // End of initialization block. Revert to fast case. The
3729 // argument to the runtime call is the receiver, which is the
3730 // first value pushed as part of the reference, which is below
3731 // the lhs value.
3732 frame_->PushElementAt(target.size());
3733 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
3734 }
3682 } 3735 }
3683 } 3736 }
3684 } 3737 }
3685 3738
3686 3739
3687 void CodeGenerator::VisitThrow(Throw* node) { 3740 void CodeGenerator::VisitThrow(Throw* node) {
3688 Comment cmnt(masm_, "[ Throw"); 3741 Comment cmnt(masm_, "[ Throw");
3689 CodeForStatementPosition(node); 3742 CodeForStatementPosition(node);
3690 3743
3691 Load(node->exception()); 3744 Load(node->exception());
(...skipping 2187 matching lines...) Expand 10 before | Expand all | Expand 10 after
5879 } 5932 }
5880 case Token::BIT_OR: 5933 case Token::BIT_OR:
5881 case Token::BIT_AND: 5934 case Token::BIT_AND:
5882 case Token::BIT_XOR: 5935 case Token::BIT_XOR:
5883 case Token::SAR: 5936 case Token::SAR:
5884 case Token::SHL: 5937 case Token::SHL:
5885 case Token::SHR: { 5938 case Token::SHR: {
5886 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 5939 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
5887 FloatingPointHelper::LoadFloatOperands(masm, ecx); 5940 FloatingPointHelper::LoadFloatOperands(masm, ecx);
5888 5941
5889 Label non_int32_operands, non_smi_result, skip_allocation; 5942 Label skip_allocation, non_smi_result, operand_conversion_failure;
5943
5890 // Reserve space for converted numbers. 5944 // Reserve space for converted numbers.
5891 __ sub(Operand(esp), Immediate(2 * kPointerSize)); 5945 __ sub(Operand(esp), Immediate(2 * kPointerSize));
5892 5946
5893 // Check if right operand is int32. 5947 bool use_sse3 = CpuFeatures::IsSupported(CpuFeatures::SSE3);
5894 __ fist_s(Operand(esp, 1 * kPointerSize)); 5948 if (use_sse3) {
5895 __ fild_s(Operand(esp, 1 * kPointerSize)); 5949 // Truncate the operands to 32-bit integers and check for
5896 __ fucompp(); 5950 // exceptions in doing so.
5897 __ fnstsw_ax(); 5951 CpuFeatures::Scope scope(CpuFeatures::SSE3);
5898 __ sahf(); 5952 __ fisttp_s(Operand(esp, 0 * kPointerSize));
5899 __ j(not_zero, &non_int32_operands); 5953 __ fisttp_s(Operand(esp, 1 * kPointerSize));
5900 __ j(parity_even, &non_int32_operands); 5954 __ fnstsw_ax();
5955 __ test(eax, Immediate(1));
5956 __ j(not_zero, &operand_conversion_failure);
5957 } else {
5958 // Check if right operand is int32.
5959 __ fist_s(Operand(esp, 0 * kPointerSize));
5960 __ fild_s(Operand(esp, 0 * kPointerSize));
5961 __ fucompp();
5962 __ fnstsw_ax();
5963 __ sahf();
5964 __ j(not_zero, &operand_conversion_failure);
5965 __ j(parity_even, &operand_conversion_failure);
5901 5966
5902 // Check if left operand is int32. 5967 // Check if left operand is int32.
5903 __ fist_s(Operand(esp, 0 * kPointerSize)); 5968 __ fist_s(Operand(esp, 1 * kPointerSize));
5904 __ fild_s(Operand(esp, 0 * kPointerSize)); 5969 __ fild_s(Operand(esp, 1 * kPointerSize));
5905 __ fucompp(); 5970 __ fucompp();
5906 __ fnstsw_ax(); 5971 __ fnstsw_ax();
5907 __ sahf(); 5972 __ sahf();
5908 __ j(not_zero, &non_int32_operands); 5973 __ j(not_zero, &operand_conversion_failure);
5909 __ j(parity_even, &non_int32_operands); 5974 __ j(parity_even, &operand_conversion_failure);
5975 }
5910 5976
5911 // Get int32 operands and perform bitop. 5977 // Get int32 operands and perform bitop.
5978 __ pop(ecx);
5912 __ pop(eax); 5979 __ pop(eax);
5913 __ pop(ecx);
5914 switch (op_) { 5980 switch (op_) {
5915 case Token::BIT_OR: __ or_(eax, Operand(ecx)); break; 5981 case Token::BIT_OR: __ or_(eax, Operand(ecx)); break;
5916 case Token::BIT_AND: __ and_(eax, Operand(ecx)); break; 5982 case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
5917 case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break; 5983 case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break;
5918 case Token::SAR: __ sar(eax); break; 5984 case Token::SAR: __ sar(eax); break;
5919 case Token::SHL: __ shl(eax); break; 5985 case Token::SHL: __ shl(eax); break;
5920 case Token::SHR: __ shr(eax); break; 5986 case Token::SHR: __ shr(eax); break;
5921 default: UNREACHABLE(); 5987 default: UNREACHABLE();
5922 } 5988 }
5923 5989
(...skipping 27 matching lines...) Expand all
5951 __ bind(&skip_allocation); 6017 __ bind(&skip_allocation);
5952 break; 6018 break;
5953 default: UNREACHABLE(); 6019 default: UNREACHABLE();
5954 } 6020 }
5955 // Store the result in the HeapNumber and return. 6021 // Store the result in the HeapNumber and return.
5956 __ mov(Operand(esp, 1 * kPointerSize), ebx); 6022 __ mov(Operand(esp, 1 * kPointerSize), ebx);
5957 __ fild_s(Operand(esp, 1 * kPointerSize)); 6023 __ fild_s(Operand(esp, 1 * kPointerSize));
5958 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 6024 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
5959 __ ret(2 * kPointerSize); 6025 __ ret(2 * kPointerSize);
5960 } 6026 }
5961 __ bind(&non_int32_operands); 6027
5962 // Restore stacks and operands before calling runtime. 6028 // Clear the FPU exception flag and reset the stack before calling
5963 __ ffree(0); 6029 // the runtime system.
6030 __ bind(&operand_conversion_failure);
5964 __ add(Operand(esp), Immediate(2 * kPointerSize)); 6031 __ add(Operand(esp), Immediate(2 * kPointerSize));
6032 if (use_sse3) {
6033 // If we've used the SSE3 instructions for truncating the
6034 // floating point values to integers and it failed, we have a
6035 // pending #IA exception. Clear it.
6036 __ fnclex();
6037 } else {
6038 // The non-SSE3 variant does early bailout if the right
6039 // operand isn't a 32-bit integer, so we may have a single
6040 // value on the FPU stack we need to get rid of.
6041 __ ffree(0);
6042 }
5965 6043
5966 // SHR should return uint32 - go to runtime for non-smi/negative result. 6044 // SHR should return uint32 - go to runtime for non-smi/negative result.
5967 if (op_ == Token::SHR) __ bind(&non_smi_result); 6045 if (op_ == Token::SHR) __ bind(&non_smi_result);
5968 __ mov(eax, Operand(esp, 1 * kPointerSize)); 6046 __ mov(eax, Operand(esp, 1 * kPointerSize));
5969 __ mov(edx, Operand(esp, 2 * kPointerSize)); 6047 __ mov(edx, Operand(esp, 2 * kPointerSize));
5970 break; 6048 break;
5971 } 6049 }
5972 default: UNREACHABLE(); break; 6050 default: UNREACHABLE(); break;
5973 } 6051 }
5974 6052
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after
6826 6904
6827 // Slow-case: Go through the JavaScript implementation. 6905 // Slow-case: Go through the JavaScript implementation.
6828 __ bind(&slow); 6906 __ bind(&slow);
6829 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6907 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6830 } 6908 }
6831 6909
6832 6910
6833 #undef __ 6911 #undef __
6834 6912
6835 } } // namespace v8::internal 6913 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | src/compilation-cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698