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

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

Issue 545007: Introduce number type information in the virtual frame. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: merged with latest rev. Created 10 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/x64/codegen-x64.h ('k') | src/x64/macro-assembler-x64.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 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 4243 matching lines...) Expand 10 before | Expand all | Expand 10 after
4254 4254
4255 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 4255 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
4256 // convert it to a boolean in the condition code register or jump to 4256 // convert it to a boolean in the condition code register or jump to
4257 // 'false_target'/'true_target' as appropriate. 4257 // 'false_target'/'true_target' as appropriate.
4258 void CodeGenerator::ToBoolean(ControlDestination* dest) { 4258 void CodeGenerator::ToBoolean(ControlDestination* dest) {
4259 Comment cmnt(masm_, "[ ToBoolean"); 4259 Comment cmnt(masm_, "[ ToBoolean");
4260 4260
4261 // The value to convert should be popped from the frame. 4261 // The value to convert should be popped from the frame.
4262 Result value = frame_->Pop(); 4262 Result value = frame_->Pop();
4263 value.ToRegister(); 4263 value.ToRegister();
4264 // Fast case checks.
4265 4264
4266 // 'false' => false. 4265 if (value.is_number()) {
4267 __ CompareRoot(value.reg(), Heap::kFalseValueRootIndex); 4266 Comment cmnt(masm_, "ONLY_NUMBER");
4268 dest->false_target()->Branch(equal); 4267 // Fast case if NumberInfo indicates only numbers.
4268 if (FLAG_debug_code) {
4269 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
4270 }
4271 // Smi => false iff zero.
4272 __ SmiCompare(value.reg(), Smi::FromInt(0));
4273 dest->false_target()->Branch(equal);
4274 Condition is_smi = masm_->CheckSmi(value.reg());
4275 dest->true_target()->Branch(is_smi);
4276 __ fldz();
4277 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
4278 __ FCmp();
4279 value.Unuse();
4280 dest->Split(not_zero);
4281 } else {
4282 // Fast case checks.
4283 // 'false' => false.
4284 __ CompareRoot(value.reg(), Heap::kFalseValueRootIndex);
4285 dest->false_target()->Branch(equal);
4269 4286
4270 // 'true' => true. 4287 // 'true' => true.
4271 __ CompareRoot(value.reg(), Heap::kTrueValueRootIndex); 4288 __ CompareRoot(value.reg(), Heap::kTrueValueRootIndex);
4272 dest->true_target()->Branch(equal); 4289 dest->true_target()->Branch(equal);
4273 4290
4274 // 'undefined' => false. 4291 // 'undefined' => false.
4275 __ CompareRoot(value.reg(), Heap::kUndefinedValueRootIndex); 4292 __ CompareRoot(value.reg(), Heap::kUndefinedValueRootIndex);
4276 dest->false_target()->Branch(equal); 4293 dest->false_target()->Branch(equal);
4277 4294
4278 // Smi => false iff zero. 4295 // Smi => false iff zero.
4279 __ SmiCompare(value.reg(), Smi::FromInt(0)); 4296 __ SmiCompare(value.reg(), Smi::FromInt(0));
4280 dest->false_target()->Branch(equal); 4297 dest->false_target()->Branch(equal);
4281 Condition is_smi = masm_->CheckSmi(value.reg()); 4298 Condition is_smi = masm_->CheckSmi(value.reg());
4282 dest->true_target()->Branch(is_smi); 4299 dest->true_target()->Branch(is_smi);
4283 4300
4284 // Call the stub for all other cases. 4301 // Call the stub for all other cases.
4285 frame_->Push(&value); // Undo the Pop() from above. 4302 frame_->Push(&value); // Undo the Pop() from above.
4286 ToBooleanStub stub; 4303 ToBooleanStub stub;
4287 Result temp = frame_->CallStub(&stub, 1); 4304 Result temp = frame_->CallStub(&stub, 1);
4288 // Convert the result to a condition code. 4305 // Convert the result to a condition code.
4289 __ testq(temp.reg(), temp.reg()); 4306 __ testq(temp.reg(), temp.reg());
4290 temp.Unuse(); 4307 temp.Unuse();
4291 dest->Split(not_equal); 4308 dest->Split(not_equal);
4309 }
4292 } 4310 }
4293 4311
4294 4312
4295 void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) { 4313 void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) {
4296 UNIMPLEMENTED(); 4314 UNIMPLEMENTED();
4297 // TODO(X64): Implement security policy for loads of smis. 4315 // TODO(X64): Implement security policy for loads of smis.
4298 } 4316 }
4299 4317
4300 4318
4301 bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) { 4319 bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) {
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
5148 } else if (right_is_string) { 5166 } else if (right_is_string) {
5149 answer = 5167 answer =
5150 frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2); 5168 frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
5151 } 5169 }
5152 frame_->Push(&answer); 5170 frame_->Push(&answer);
5153 return; 5171 return;
5154 } 5172 }
5155 // Neither operand is known to be a string. 5173 // Neither operand is known to be a string.
5156 } 5174 }
5157 5175
5158 bool left_is_smi = left.is_constant() && left.handle()->IsSmi(); 5176 bool left_is_smi_constant = left.is_constant() && left.handle()->IsSmi();
5159 bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi(); 5177 bool left_is_non_smi_constant = left.is_constant() && !left.handle()->IsSmi();
5160 bool right_is_smi = right.is_constant() && right.handle()->IsSmi(); 5178 bool right_is_smi_constant = right.is_constant() && right.handle()->IsSmi();
5161 bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi(); 5179 bool right_is_non_smi_constant =
5180 right.is_constant() && !right.handle()->IsSmi();
5162 5181
5163 if (left_is_smi && right_is_smi) { 5182 if (left_is_smi_constant && right_is_smi_constant) {
5164 // Compute the constant result at compile time, and leave it on the frame. 5183 // Compute the constant result at compile time, and leave it on the frame.
5165 int left_int = Smi::cast(*left.handle())->value(); 5184 int left_int = Smi::cast(*left.handle())->value();
5166 int right_int = Smi::cast(*right.handle())->value(); 5185 int right_int = Smi::cast(*right.handle())->value();
5167 if (FoldConstantSmis(op, left_int, right_int)) return; 5186 if (FoldConstantSmis(op, left_int, right_int)) return;
5168 } 5187 }
5169 5188
5189 // Get number type of left and right sub-expressions.
5190 bool only_numbers = left.is_number() && right.is_number();
5191 bool only_smis = left.is_smi() && right.is_smi();
5192
5170 Result answer; 5193 Result answer;
5171 if (left_is_non_smi || right_is_non_smi) { 5194 if (left_is_non_smi_constant || right_is_non_smi_constant) {
5172 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB); 5195 GenericBinaryOpStub stub(op,
5196 overwrite_mode,
5197 NO_SMI_CODE_IN_STUB,
5198 only_numbers);
5173 answer = stub.GenerateCall(masm_, frame_, &left, &right); 5199 answer = stub.GenerateCall(masm_, frame_, &left, &right);
5174 } else if (right_is_smi) { 5200 } else if (right_is_smi_constant) {
5175 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), 5201 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
5176 type, false, overwrite_mode); 5202 type, false, overwrite_mode);
5177 } else if (left_is_smi) { 5203 } else if (left_is_smi_constant) {
5178 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), 5204 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
5179 type, true, overwrite_mode); 5205 type, true, overwrite_mode);
5180 } else { 5206 } else {
5181 // Set the flags based on the operation, type and loop nesting level. 5207 // Set the flags based on the operation, type and loop nesting level.
5182 // Bit operations always assume they likely operate on Smis. Still only 5208 // Bit operations always assume they likely operate on Smis. Still only
5183 // generate the inline Smi check code if this operation is part of a loop. 5209 // generate the inline Smi check code if this operation is part of a loop.
5184 // For all other operations only inline the Smi check code for likely smis 5210 // For all other operations only inline the Smi check code for likely smis
5185 // if the operation is part of a loop. 5211 // if the operation is part of a loop.
5186 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { 5212 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
5187 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); 5213 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
5188 } else { 5214 } else {
5189 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS); 5215 GenericBinaryOpStub stub(op,
5216 overwrite_mode,
5217 NO_GENERIC_BINARY_FLAGS,
5218 only_numbers);
5190 answer = stub.GenerateCall(masm_, frame_, &left, &right); 5219 answer = stub.GenerateCall(masm_, frame_, &left, &right);
5191 } 5220 }
5192 } 5221 }
5222
5223 // Set NumberInfo of result according to the operation performed.
5224 NumberInfo::Type info = NumberInfo::kUnknown;
5225 switch (op) {
5226 case Token::COMMA:
5227 info = right.number_info();
5228 break;
5229 case Token::OR:
5230 case Token::AND:
5231 // Could be anything. Check inputs.
5232 if (only_numbers)
5233 info = NumberInfo::kNumber;
5234 break;
5235 case Token::BIT_OR:
5236 case Token::BIT_XOR:
5237 case Token::BIT_AND:
5238 case Token::SAR:
5239 case Token::SHR:
5240 // TODO(fsc): Make use of the fact that smis are 32 bits on x64.
5241 info = only_smis ? NumberInfo::kSmi : NumberInfo::kNumber;
5242 break;
5243 case Token::SHL:
5244 info = NumberInfo::kNumber;
5245 break;
5246 case Token::ADD:
5247 // Could be strings or numbers. Check types of inputs.
5248 if (only_numbers) {
5249 info = NumberInfo::kNumber;
5250 }
5251 break;
5252 case Token::SUB:
5253 case Token::MUL:
5254 case Token::DIV:
5255 case Token::MOD:
5256 info = NumberInfo::kNumber;
5257 break;
5258 default:
5259 UNREACHABLE();
5260 }
5261 answer.set_number_info(info);
5193 frame_->Push(&answer); 5262 frame_->Push(&answer);
5194 } 5263 }
5195 5264
5196 5265
5197 // Emit a LoadIC call to get the value from receiver and leave it in 5266 // Emit a LoadIC call to get the value from receiver and leave it in
5198 // dst. The receiver register is restored after the call. 5267 // dst. The receiver register is restored after the call.
5199 class DeferredReferenceGetNamedValue: public DeferredCode { 5268 class DeferredReferenceGetNamedValue: public DeferredCode {
5200 public: 5269 public:
5201 DeferredReferenceGetNamedValue(Register dst, 5270 DeferredReferenceGetNamedValue(Register dst,
5202 Register receiver, 5271 Register receiver,
(...skipping 2868 matching lines...) Expand 10 before | Expand all | Expand 10 after
8071 const char* op_name = Token::Name(op_); 8140 const char* op_name = Token::Name(op_);
8072 const char* overwrite_name; 8141 const char* overwrite_name;
8073 switch (mode_) { 8142 switch (mode_) {
8074 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 8143 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
8075 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 8144 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
8076 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 8145 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
8077 default: overwrite_name = "UnknownOverwrite"; break; 8146 default: overwrite_name = "UnknownOverwrite"; break;
8078 } 8147 }
8079 8148
8080 OS::SNPrintF(Vector<char>(name_, len), 8149 OS::SNPrintF(Vector<char>(name_, len),
8081 "GenericBinaryOpStub_%s_%s%s_%s%s_%s", 8150 "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s",
8082 op_name, 8151 op_name,
8083 overwrite_name, 8152 overwrite_name,
8084 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 8153 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
8085 args_in_registers_ ? "RegArgs" : "StackArgs", 8154 args_in_registers_ ? "RegArgs" : "StackArgs",
8086 args_reversed_ ? "_R" : "", 8155 args_reversed_ ? "_R" : "",
8087 use_sse3_ ? "SSE3" : "SSE2"); 8156 use_sse3_ ? "SSE3" : "SSE2",
8157 only_numbers_in_stub_ ? "_OnlyNumbers" : "");
8088 return name_; 8158 return name_;
8089 } 8159 }
8090 8160
8091 8161
8092 void GenericBinaryOpStub::GenerateCall( 8162 void GenericBinaryOpStub::GenerateCall(
8093 MacroAssembler* masm, 8163 MacroAssembler* masm,
8094 Register left, 8164 Register left,
8095 Register right) { 8165 Register right) {
8096 if (!ArgsInRegistersSupported()) { 8166 if (!ArgsInRegistersSupported()) {
8097 // Pass arguments on the stack. 8167 // Pass arguments on the stack.
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
8401 GenerateLoadArguments(masm); 8471 GenerateLoadArguments(masm);
8402 } 8472 }
8403 // Floating point case. 8473 // Floating point case.
8404 switch (op_) { 8474 switch (op_) {
8405 case Token::ADD: 8475 case Token::ADD:
8406 case Token::SUB: 8476 case Token::SUB:
8407 case Token::MUL: 8477 case Token::MUL:
8408 case Token::DIV: { 8478 case Token::DIV: {
8409 // rax: y 8479 // rax: y
8410 // rdx: x 8480 // rdx: x
8411 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); 8481 if (only_numbers_in_stub_) {
8482 if (FLAG_debug_code) {
8483 // Assert at runtime that inputs are only numbers.
8484 __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
8485 __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
8486 }
8487 } else {
8488 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
8489 }
8412 // Fast-case: Both operands are numbers. 8490 // Fast-case: Both operands are numbers.
8413 // xmm4 and xmm5 are volatile XMM registers. 8491 // xmm4 and xmm5 are volatile XMM registers.
8414 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5); 8492 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
8415 8493
8416 switch (op_) { 8494 switch (op_) {
8417 case Token::ADD: __ addsd(xmm4, xmm5); break; 8495 case Token::ADD: __ addsd(xmm4, xmm5); break;
8418 case Token::SUB: __ subsd(xmm4, xmm5); break; 8496 case Token::SUB: __ subsd(xmm4, xmm5); break;
8419 case Token::MUL: __ mulsd(xmm4, xmm5); break; 8497 case Token::MUL: __ mulsd(xmm4, xmm5); break;
8420 case Token::DIV: __ divsd(xmm4, xmm5); break; 8498 case Token::DIV: __ divsd(xmm4, xmm5); break;
8421 default: UNREACHABLE(); 8499 default: UNREACHABLE();
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
9297 // Call the function from C++. 9375 // Call the function from C++.
9298 return FUNCTION_CAST<ModuloFunction>(buffer); 9376 return FUNCTION_CAST<ModuloFunction>(buffer);
9299 } 9377 }
9300 9378
9301 #endif 9379 #endif
9302 9380
9303 9381
9304 #undef __ 9382 #undef __
9305 9383
9306 } } // namespace v8::internal 9384 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698