OLD | NEW |
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 5223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5234 cc = ReverseCondition(cc); | 5234 cc = ReverseCondition(cc); |
5235 left_side = frame_->Pop(); | 5235 left_side = frame_->Pop(); |
5236 right_side = frame_->Pop(); | 5236 right_side = frame_->Pop(); |
5237 } else { | 5237 } else { |
5238 right_side = frame_->Pop(); | 5238 right_side = frame_->Pop(); |
5239 left_side = frame_->Pop(); | 5239 left_side = frame_->Pop(); |
5240 } | 5240 } |
5241 ASSERT(cc == less || cc == equal || cc == greater_equal); | 5241 ASSERT(cc == less || cc == equal || cc == greater_equal); |
5242 | 5242 |
5243 // If either side is a constant smi, optimize the comparison. | 5243 // If either side is a constant smi, optimize the comparison. |
5244 bool left_side_constant_smi = | 5244 bool left_side_constant_smi = false; |
5245 left_side.is_constant() && left_side.handle()->IsSmi(); | 5245 bool left_side_constant_null = false; |
5246 bool right_side_constant_smi = | 5246 bool left_side_constant_1_char_string = false; |
5247 right_side.is_constant() && right_side.handle()->IsSmi(); | 5247 if (left_side.is_constant()) { |
5248 bool left_side_constant_null = | 5248 left_side_constant_smi = left_side.handle()->IsSmi(); |
5249 left_side.is_constant() && left_side.handle()->IsNull(); | 5249 left_side_constant_null = left_side.handle()->IsNull(); |
5250 bool right_side_constant_null = | 5250 left_side_constant_1_char_string = |
5251 right_side.is_constant() && right_side.handle()->IsNull(); | 5251 (left_side.handle()->IsString() && |
| 5252 String::cast(*left_side.handle())->length() == 1 && |
| 5253 String::cast(*left_side.handle())->IsAsciiRepresentation()); |
| 5254 } |
| 5255 bool right_side_constant_smi = false; |
| 5256 bool right_side_constant_null = false; |
| 5257 bool right_side_constant_1_char_string = false; |
| 5258 if (right_side.is_constant()) { |
| 5259 right_side_constant_smi = right_side.handle()->IsSmi(); |
| 5260 right_side_constant_null = right_side.handle()->IsNull(); |
| 5261 right_side_constant_1_char_string = |
| 5262 (right_side.handle()->IsString() && |
| 5263 String::cast(*right_side.handle())->length() == 1 && |
| 5264 String::cast(*right_side.handle())->IsAsciiRepresentation()); |
| 5265 } |
5252 | 5266 |
5253 if (left_side_constant_smi || right_side_constant_smi) { | 5267 if (left_side_constant_smi || right_side_constant_smi) { |
5254 if (left_side_constant_smi && right_side_constant_smi) { | 5268 if (left_side_constant_smi && right_side_constant_smi) { |
5255 // Trivial case, comparing two constants. | 5269 // Trivial case, comparing two constants. |
5256 int left_value = Smi::cast(*left_side.handle())->value(); | 5270 int left_value = Smi::cast(*left_side.handle())->value(); |
5257 int right_value = Smi::cast(*right_side.handle())->value(); | 5271 int right_value = Smi::cast(*right_side.handle())->value(); |
5258 switch (cc) { | 5272 switch (cc) { |
5259 case less: | 5273 case less: |
5260 dest->Goto(left_value < right_value); | 5274 dest->Goto(left_value < right_value); |
5261 break; | 5275 break; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5381 Result temp = allocator()->Allocate(); | 5395 Result temp = allocator()->Allocate(); |
5382 ASSERT(temp.is_valid()); | 5396 ASSERT(temp.is_valid()); |
5383 __ movq(temp.reg(), | 5397 __ movq(temp.reg(), |
5384 FieldOperand(operand.reg(), HeapObject::kMapOffset)); | 5398 FieldOperand(operand.reg(), HeapObject::kMapOffset)); |
5385 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset), | 5399 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset), |
5386 Immediate(1 << Map::kIsUndetectable)); | 5400 Immediate(1 << Map::kIsUndetectable)); |
5387 temp.Unuse(); | 5401 temp.Unuse(); |
5388 operand.Unuse(); | 5402 operand.Unuse(); |
5389 dest->Split(not_zero); | 5403 dest->Split(not_zero); |
5390 } | 5404 } |
| 5405 } else if (left_side_constant_1_char_string || |
| 5406 right_side_constant_1_char_string) { |
| 5407 if (left_side_constant_1_char_string && right_side_constant_1_char_string) { |
| 5408 // Trivial case, comparing two constants. |
| 5409 int left_value = String::cast(*left_side.handle())->Get(0); |
| 5410 int right_value = String::cast(*right_side.handle())->Get(0); |
| 5411 switch (cc) { |
| 5412 case less: |
| 5413 dest->Goto(left_value < right_value); |
| 5414 break; |
| 5415 case equal: |
| 5416 dest->Goto(left_value == right_value); |
| 5417 break; |
| 5418 case greater_equal: |
| 5419 dest->Goto(left_value >= right_value); |
| 5420 break; |
| 5421 default: |
| 5422 UNREACHABLE(); |
| 5423 } |
| 5424 } else { |
| 5425 // Only one side is a constant 1 character string. |
| 5426 // If left side is a constant 1-character string, reverse the operands. |
| 5427 // Since one side is a constant string, conversion order does not matter. |
| 5428 if (left_side_constant_1_char_string) { |
| 5429 Result temp = left_side; |
| 5430 left_side = right_side; |
| 5431 right_side = temp; |
| 5432 cc = ReverseCondition(cc); |
| 5433 // This may reintroduce greater or less_equal as the value of cc. |
| 5434 // CompareStub and the inline code both support all values of cc. |
| 5435 } |
| 5436 // Implement comparison against a constant string, inlining the case |
| 5437 // where both sides are strings. |
| 5438 left_side.ToRegister(); |
| 5439 |
| 5440 // Here we split control flow to the stub call and inlined cases |
| 5441 // before finally splitting it to the control destination. We use |
| 5442 // a jump target and branching to duplicate the virtual frame at |
| 5443 // the first split. We manually handle the off-frame references |
| 5444 // by reconstituting them on the non-fall-through path. |
| 5445 JumpTarget is_not_string, is_string; |
| 5446 Register left_reg = left_side.reg(); |
| 5447 Handle<Object> right_val = right_side.handle(); |
| 5448 ASSERT(StringShape(String::cast(*right_val)).IsSymbol()); |
| 5449 Condition is_smi = masm()->CheckSmi(left_reg); |
| 5450 is_not_string.Branch(is_smi, &left_side); |
| 5451 Result temp = allocator_->Allocate(); |
| 5452 ASSERT(temp.is_valid()); |
| 5453 __ movq(temp.reg(), |
| 5454 FieldOperand(left_reg, HeapObject::kMapOffset)); |
| 5455 __ movzxbl(temp.reg(), |
| 5456 FieldOperand(temp.reg(), Map::kInstanceTypeOffset)); |
| 5457 // If we are testing for equality then make use of the symbol shortcut. |
| 5458 // Check if the left hand side has the same type as the right hand |
| 5459 // side (which is always a symbol). |
| 5460 if (cc == equal) { |
| 5461 Label not_a_symbol; |
| 5462 ASSERT(kSymbolTag != 0); |
| 5463 // Ensure that no non-strings have the symbol bit set. |
| 5464 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); |
| 5465 __ testb(temp.reg(), Immediate(kIsSymbolMask)); // Test the symbol bit. |
| 5466 __ j(zero, ¬_a_symbol); |
| 5467 // They are symbols, so do identity compare. |
| 5468 __ Cmp(left_reg, right_side.handle()); |
| 5469 dest->true_target()->Branch(equal); |
| 5470 dest->false_target()->Branch(not_equal); |
| 5471 __ bind(¬_a_symbol); |
| 5472 } |
| 5473 // Call the compare stub if the left side is not a flat ascii string. |
| 5474 __ andb(temp.reg(), |
| 5475 Immediate(kIsNotStringMask | |
| 5476 kStringRepresentationMask | |
| 5477 kStringEncodingMask)); |
| 5478 __ cmpb(temp.reg(), |
| 5479 Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); |
| 5480 temp.Unuse(); |
| 5481 is_string.Branch(equal, &left_side); |
| 5482 |
| 5483 // Setup and call the compare stub. |
| 5484 is_not_string.Bind(&left_side); |
| 5485 CompareStub stub(cc, strict, kCantBothBeNaN); |
| 5486 Result result = frame_->CallStub(&stub, &left_side, &right_side); |
| 5487 result.ToRegister(); |
| 5488 __ SmiCompare(result.reg(), Smi::FromInt(0)); |
| 5489 result.Unuse(); |
| 5490 dest->true_target()->Branch(cc); |
| 5491 dest->false_target()->Jump(); |
| 5492 |
| 5493 is_string.Bind(&left_side); |
| 5494 // left_side is a sequential ASCII string. |
| 5495 ASSERT(left_side.reg().is(left_reg)); |
| 5496 right_side = Result(right_val); |
| 5497 Result temp2 = allocator_->Allocate(); |
| 5498 ASSERT(temp2.is_valid()); |
| 5499 // Test string equality and comparison. |
| 5500 if (cc == equal) { |
| 5501 Label comparison_done; |
| 5502 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset), |
| 5503 Immediate(1)); |
| 5504 __ j(not_equal, &comparison_done); |
| 5505 uint8_t char_value = |
| 5506 static_cast<uint8_t>(String::cast(*right_val)->Get(0)); |
| 5507 __ cmpb(FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize), |
| 5508 Immediate(char_value)); |
| 5509 __ bind(&comparison_done); |
| 5510 } else { |
| 5511 __ movl(temp2.reg(), |
| 5512 FieldOperand(left_side.reg(), String::kLengthOffset)); |
| 5513 __ subl(temp2.reg(), Immediate(1)); |
| 5514 Label comparison; |
| 5515 // If the length is 0 then the subtraction gave -1 which compares less |
| 5516 // than any character. |
| 5517 __ j(negative, &comparison); |
| 5518 // Otherwise load the first character. |
| 5519 __ movzxbl(temp2.reg(), |
| 5520 FieldOperand(left_side.reg(), SeqAsciiString::kHeaderSize)); |
| 5521 __ bind(&comparison); |
| 5522 // Compare the first character of the string with the |
| 5523 // constant 1-character string. |
| 5524 uint8_t char_value = |
| 5525 static_cast<uint8_t>(String::cast(*right_side.handle())->Get(0)); |
| 5526 __ cmpb(temp2.reg(), Immediate(char_value)); |
| 5527 Label characters_were_different; |
| 5528 __ j(not_equal, &characters_were_different); |
| 5529 // If the first character is the same then the long string sorts after |
| 5530 // the short one. |
| 5531 __ cmpl(FieldOperand(left_side.reg(), String::kLengthOffset), |
| 5532 Immediate(1)); |
| 5533 __ bind(&characters_were_different); |
| 5534 } |
| 5535 temp2.Unuse(); |
| 5536 left_side.Unuse(); |
| 5537 right_side.Unuse(); |
| 5538 dest->Split(cc); |
| 5539 } |
5391 } else { // Neither side is a constant Smi or null. | 5540 } else { // Neither side is a constant Smi or null. |
5392 // If either side is a non-smi constant, skip the smi check. | 5541 // If either side is a non-smi constant, skip the smi check. |
5393 bool known_non_smi = | 5542 bool known_non_smi = |
5394 (left_side.is_constant() && !left_side.handle()->IsSmi()) || | 5543 (left_side.is_constant() && !left_side.handle()->IsSmi()) || |
5395 (right_side.is_constant() && !right_side.handle()->IsSmi()); | 5544 (right_side.is_constant() && !right_side.handle()->IsSmi()); |
5396 left_side.ToRegister(); | 5545 left_side.ToRegister(); |
5397 right_side.ToRegister(); | 5546 right_side.ToRegister(); |
5398 | 5547 |
5399 if (known_non_smi) { | 5548 if (known_non_smi) { |
5400 // When non-smi, call out to the compare stub. | 5549 // When non-smi, call out to the compare stub. |
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10204 // Call the function from C++. | 10353 // Call the function from C++. |
10205 return FUNCTION_CAST<ModuloFunction>(buffer); | 10354 return FUNCTION_CAST<ModuloFunction>(buffer); |
10206 } | 10355 } |
10207 | 10356 |
10208 #endif | 10357 #endif |
10209 | 10358 |
10210 | 10359 |
10211 #undef __ | 10360 #undef __ |
10212 | 10361 |
10213 } } // namespace v8::internal | 10362 } } // namespace v8::internal |
OLD | NEW |