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

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

Issue 18402: Remove spilled code from special cases of comparison. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 11 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 | 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 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 4087 matching lines...) Expand 10 before | Expand all | Expand 10 after
4098 // literal 'null'. If so, we optimize the code by inlining a null check 4098 // literal 'null'. If so, we optimize the code by inlining a null check
4099 // instead of calling the (very) general runtime routine for checking 4099 // instead of calling the (very) general runtime routine for checking
4100 // equality. 4100 // equality.
4101 if (op == Token::EQ || op == Token::EQ_STRICT) { 4101 if (op == Token::EQ || op == Token::EQ_STRICT) {
4102 bool left_is_null = 4102 bool left_is_null =
4103 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 4103 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
4104 bool right_is_null = 4104 bool right_is_null =
4105 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 4105 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
4106 // The 'null' value can only be equal to 'null' or 'undefined'. 4106 // The 'null' value can only be equal to 'null' or 'undefined'.
4107 if (left_is_null || right_is_null) { 4107 if (left_is_null || right_is_null) {
4108 VirtualFrame::SpilledScope spilled_scope(this); 4108 Load(left_is_null ? right : left);
4109 LoadAndSpill(left_is_null ? right : left); 4109 Result operand = frame_->Pop();
4110 frame_->EmitPop(eax); 4110 operand.ToRegister();
4111 __ cmp(eax, Factory::null_value()); 4111 __ cmp(operand.reg(), Factory::null_value());
4112 Condition cc = equal;
4112 4113
4113 // The 'null' value is only equal to 'undefined' if using non-strict 4114 // The 'null' value is only equal to 'undefined' if using non-strict
4114 // comparisons. 4115 // comparisons.
4115 if (op != Token::EQ_STRICT) { 4116 if (op != Token::EQ_STRICT) {
4117 true_target()->Branch(cc);
4118 __ cmp(operand.reg(), Factory::undefined_value());
4116 true_target()->Branch(equal); 4119 true_target()->Branch(equal);
4117 4120 __ test(operand.reg(), Immediate(kSmiTagMask));
4118 __ cmp(eax, Factory::undefined_value());
4119 true_target()->Branch(equal);
4120
4121 __ test(eax, Immediate(kSmiTagMask));
4122 false_target()->Branch(equal); 4121 false_target()->Branch(equal);
4123 4122
4124 // It can be an undetectable object. 4123 // It can be an undetectable object.
4125 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 4124 // Use a scratch register in preference to spilling operand.reg().
4126 __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset)); 4125 Result temp = allocator()->Allocate();
4127 __ and_(eax, 1 << Map::kIsUndetectable); 4126 ASSERT(temp.is_valid());
4128 __ cmp(eax, 1 << Map::kIsUndetectable); 4127 __ mov(temp.reg(),
4128 FieldOperand(operand.reg(), HeapObject::kMapOffset));
4129 __ movzx_b(temp.reg(),
4130 FieldOperand(temp.reg(), Map::kBitFieldOffset));
4131 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
4132 cc = not_zero;
4129 } 4133 }
4130 4134 operand.Unuse();
4131 true_target()->Branch(equal); 4135 true_target()->Branch(cc);
4132 false_target()->Jump(); 4136 false_target()->Jump();
4133 return; 4137 return;
4134 } 4138 }
4135 } 4139 }
4136 4140
4137 // To make typeof testing for natives implemented in JavaScript really 4141 // To make typeof testing for natives implemented in JavaScript really
4138 // efficient, we generate special code for expressions of the form: 4142 // efficient, we generate special code for expressions of the form:
4139 // 'typeof <expression> == <string>'. 4143 // 'typeof <expression> == <string>'.
4140 UnaryOperation* operation = left->AsUnaryOperation(); 4144 UnaryOperation* operation = left->AsUnaryOperation();
4141 if ((op == Token::EQ || op == Token::EQ_STRICT) && 4145 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
4142 (operation != NULL && operation->op() == Token::TYPEOF) && 4146 (operation != NULL && operation->op() == Token::TYPEOF) &&
4143 (right->AsLiteral() != NULL && 4147 (right->AsLiteral() != NULL &&
4144 right->AsLiteral()->handle()->IsString())) { 4148 right->AsLiteral()->handle()->IsString())) {
4145 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 4149 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
4146 4150
4147 VirtualFrame::SpilledScope spilled_scope(this); 4151 // Load the operand and move it to a register.
4148 // Load the operand and move it to register edx. 4152 {
4149 LoadTypeofExpression(operation->expression()); 4153 // TODO(toiger): Remove spill once pending change has gone in.
4150 frame_->EmitPop(edx); 4154 VirtualFrame::SpilledScope spilled_scope(this);
4155 LoadTypeofExpression(operation->expression());
4156 }
4157 Result answer = frame_->Pop();
4158 answer.ToRegister();
4151 4159
4152 if (check->Equals(Heap::number_symbol())) { 4160 if (check->Equals(Heap::number_symbol())) {
4153 __ test(edx, Immediate(kSmiTagMask)); 4161 __ test(answer.reg(), Immediate(kSmiTagMask));
4154 true_target()->Branch(zero); 4162 true_target()->Branch(zero);
4155 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4163 frame_->Spill(answer.reg());
4156 __ cmp(edx, Factory::heap_number_map()); 4164 __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4165 __ cmp(answer.reg(), Factory::heap_number_map());
4166 answer.Unuse();
4157 true_target()->Branch(equal); 4167 true_target()->Branch(equal);
4158 false_target()->Jump(); 4168 false_target()->Jump();
4159 4169
4160 } else if (check->Equals(Heap::string_symbol())) { 4170 } else if (check->Equals(Heap::string_symbol())) {
4161 __ test(edx, Immediate(kSmiTagMask)); 4171 __ test(answer.reg(), Immediate(kSmiTagMask));
4162 false_target()->Branch(zero); 4172 false_target()->Branch(zero);
4163 4173
4164 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4174
4165 4175
4166 // It can be an undetectable string object. 4176 // It can be an undetectable string object.
4167 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 4177 Result temp = allocator()->Allocate();
4168 __ and_(ecx, 1 << Map::kIsUndetectable); 4178 ASSERT(temp.is_valid());
4169 __ cmp(ecx, 1 << Map::kIsUndetectable); 4179 __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4170 false_target()->Branch(equal); 4180 __ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kBitFieldOffset));
4171 4181 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
4172 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 4182 false_target()->Branch(not_zero);
4173 __ cmp(ecx, FIRST_NONSTRING_TYPE); 4183 __ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4184 __ movzx_b(temp.reg(),
4185 FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
4186 __ cmp(temp.reg(), FIRST_NONSTRING_TYPE);
4187 temp.Unuse();
4188 answer.Unuse();
4174 true_target()->Branch(less); 4189 true_target()->Branch(less);
4175 false_target()->Jump(); 4190 false_target()->Jump();
4176 4191
4177 } else if (check->Equals(Heap::boolean_symbol())) { 4192 } else if (check->Equals(Heap::boolean_symbol())) {
4178 __ cmp(edx, Factory::true_value()); 4193 __ cmp(answer.reg(), Factory::true_value());
4179 true_target()->Branch(equal); 4194 true_target()->Branch(equal);
4180 __ cmp(edx, Factory::false_value()); 4195 __ cmp(answer.reg(), Factory::false_value());
4196 answer.Unuse();
4181 true_target()->Branch(equal); 4197 true_target()->Branch(equal);
4182 false_target()->Jump(); 4198 false_target()->Jump();
4183 4199
4184 } else if (check->Equals(Heap::undefined_symbol())) { 4200 } else if (check->Equals(Heap::undefined_symbol())) {
4185 __ cmp(edx, Factory::undefined_value()); 4201 __ cmp(answer.reg(), Factory::undefined_value());
4186 true_target()->Branch(equal); 4202 true_target()->Branch(equal);
4187 4203
4188 __ test(edx, Immediate(kSmiTagMask)); 4204 __ test(answer.reg(), Immediate(kSmiTagMask));
4189 false_target()->Branch(zero); 4205 false_target()->Branch(zero);
4190 4206
4191 // It can be an undetectable object. 4207 // It can be an undetectable object.
4192 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4208 frame_->Spill(answer.reg());
4193 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 4209 __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4194 __ and_(ecx, 1 << Map::kIsUndetectable); 4210 __ movzx_b(answer.reg(),
4195 __ cmp(ecx, 1 << Map::kIsUndetectable); 4211 FieldOperand(answer.reg(), Map::kBitFieldOffset));
4196 true_target()->Branch(equal); 4212 __ test(answer.reg(), Immediate(1 << Map::kIsUndetectable));
4213 answer.Unuse();
4214 true_target()->Branch(not_zero);
4197 false_target()->Jump(); 4215 false_target()->Jump();
4198 4216
4199 } else if (check->Equals(Heap::function_symbol())) { 4217 } else if (check->Equals(Heap::function_symbol())) {
4200 __ test(edx, Immediate(kSmiTagMask)); 4218 __ test(answer.reg(), Immediate(kSmiTagMask));
4201 false_target()->Branch(zero); 4219 false_target()->Branch(zero);
4202 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4220 frame_->Spill(answer.reg());
4203 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); 4221 __ mov(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4204 __ cmp(edx, JS_FUNCTION_TYPE); 4222 __ movzx_b(answer.reg(),
4223 FieldOperand(answer.reg(), Map::kInstanceTypeOffset));
4224 __ cmp(answer.reg(), JS_FUNCTION_TYPE);
4225 answer.Unuse();
4205 true_target()->Branch(equal); 4226 true_target()->Branch(equal);
4206 false_target()->Jump(); 4227 false_target()->Jump();
4207 4228
4208 } else if (check->Equals(Heap::object_symbol())) { 4229 } else if (check->Equals(Heap::object_symbol())) {
4209 __ test(edx, Immediate(kSmiTagMask)); 4230 __ test(answer.reg(), Immediate(kSmiTagMask));
4210 false_target()->Branch(zero); 4231 false_target()->Branch(zero);
4211 4232 __ cmp(answer.reg(), Factory::null_value());
4212 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
4213 __ cmp(edx, Factory::null_value());
4214 true_target()->Branch(equal); 4233 true_target()->Branch(equal);
4215 4234
4216 // It can be an undetectable object. 4235 // It can be an undetectable object.
4217 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset)); 4236 Result map = allocator()->Allocate();
4218 __ and_(edx, 1 << Map::kIsUndetectable); 4237 ASSERT(map.is_valid());
4219 __ cmp(edx, 1 << Map::kIsUndetectable); 4238 __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4220 false_target()->Branch(equal); 4239 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset));
4221 4240 __ test(map.reg(), Immediate(1 << Map::kIsUndetectable));
4222 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 4241 false_target()->Branch(not_zero);
4223 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 4242 __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
4243 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
4244 __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
4224 false_target()->Branch(less); 4245 false_target()->Branch(less);
4225 __ cmp(ecx, LAST_JS_OBJECT_TYPE); 4246 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
4247 answer.Unuse();
4248 map.Unuse();
4226 true_target()->Branch(less_equal); 4249 true_target()->Branch(less_equal);
4227 false_target()->Jump(); 4250 false_target()->Jump();
4228
4229 } else { 4251 } else {
4230 // Uncommon case: typeof testing against a string literal that is 4252 // Uncommon case: typeof testing against a string literal that is
4231 // never returned from the typeof operator. 4253 // never returned from the typeof operator.
4254 answer.Unuse();
4232 false_target()->Jump(); 4255 false_target()->Jump();
4233 } 4256 }
4234 return; 4257 return;
4235 } 4258 }
4236 4259
4237 Condition cc = no_condition; 4260 Condition cc = no_condition;
4238 bool strict = false; 4261 bool strict = false;
4239 switch (op) { 4262 switch (op) {
4240 case Token::EQ_STRICT: 4263 case Token::EQ_STRICT:
4241 strict = true; 4264 strict = true;
4242 // Fall through 4265 // Fall through
4243 case Token::EQ: 4266 case Token::EQ:
4244 cc = equal; 4267 cc = equal;
4245 break; 4268 break;
4246 case Token::LT: 4269 case Token::LT:
4247 cc = less; 4270 cc = less;
4248 break; 4271 break;
4249 case Token::GT: 4272 case Token::GT:
4250 cc = greater; 4273 cc = greater;
4251 break; 4274 break;
4252 case Token::LTE: 4275 case Token::LTE:
4253 cc = less_equal; 4276 cc = less_equal;
4254 break; 4277 break;
4255 case Token::GTE: 4278 case Token::GTE:
4256 cc = greater_equal; 4279 cc = greater_equal;
4257 break; 4280 break;
4258 case Token::IN: { 4281 case Token::IN: {
4259 Load(left); 4282 Load(left);
4260 Load(right); 4283 Load(right);
4284 // TODO(toiger): Fix once pending change is submitted.
4261 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); 4285 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
4262 frame_->Push(eax); // push the result 4286 frame_->Push(eax); // push the result
4263 return; 4287 return;
4264 } 4288 }
4265 case Token::INSTANCEOF: { 4289 case Token::INSTANCEOF: {
4266 Load(left); 4290 Load(left);
4267 Load(right); 4291 Load(right);
4268 InstanceofStub stub; 4292 InstanceofStub stub;
4269 frame_->CallStub(&stub, 2); 4293 Result answer = frame_->CallStub(&stub, 2);
4270 __ test(eax, Operand(eax)); 4294 answer.ToRegister();
4295 __ test(answer.reg(), Operand(answer.reg()));
4296 answer.Unuse();
4271 true_target()->Branch(zero); 4297 true_target()->Branch(zero);
4272 false_target()->Jump(); 4298 false_target()->Jump();
4273 return; 4299 return;
4274 } 4300 }
4275 default: 4301 default:
4276 UNREACHABLE(); 4302 UNREACHABLE();
4277 } 4303 }
4278 4304
4279 // Optimize for the case where (at least) one of the expressions 4305 // Optimize for the case where (at least) one of the expressions
4280 // is a literal small integer. 4306 // is a literal small integer.
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after
6084 6110
6085 // Slow-case: Go through the JavaScript implementation. 6111 // Slow-case: Go through the JavaScript implementation.
6086 __ bind(&slow); 6112 __ bind(&slow);
6087 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6113 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6088 } 6114 }
6089 6115
6090 6116
6091 #undef __ 6117 #undef __
6092 6118
6093 } } // namespace v8::internal 6119 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698