| OLD | NEW | 
|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 15 matching lines...) Expand all  Loading... | 
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 | 27 | 
| 28 #include "v8.h" | 28 #include "v8.h" | 
| 29 | 29 | 
| 30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if defined(V8_TARGET_ARCH_IA32) | 
| 31 | 31 | 
| 32 #include "ia32/lithium-codegen-ia32.h" | 32 #include "ia32/lithium-codegen-ia32.h" | 
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" | 
| 34 #include "deoptimizer.h" | 34 #include "deoptimizer.h" | 
| 35 #include "stub-cache.h" | 35 #include "stub-cache.h" | 
|  | 36 #include "codegen.h" | 
| 36 | 37 | 
| 37 namespace v8 { | 38 namespace v8 { | 
| 38 namespace internal { | 39 namespace internal { | 
| 39 | 40 | 
| 40 | 41 | 
| 41 // When invoking builtins, we need to record the safepoint in the middle of | 42 // When invoking builtins, we need to record the safepoint in the middle of | 
| 42 // the invoke instruction sequence generated by the macro assembler. | 43 // the invoke instruction sequence generated by the macro assembler. | 
| 43 class SafepointGenerator : public CallWrapper { | 44 class SafepointGenerator : public CallWrapper { | 
| 44  public: | 45  public: | 
| 45   SafepointGenerator(LCodeGen* codegen, | 46   SafepointGenerator(LCodeGen* codegen, | 
| (...skipping 1630 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1676   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1677   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 
| 1677   Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1678   Label* true_label = chunk_->GetAssemblyLabel(true_block); | 
| 1678   Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1679   Label* false_label = chunk_->GetAssemblyLabel(false_block); | 
| 1679 | 1680 | 
| 1680   Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); | 1681   Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); | 
| 1681 | 1682 | 
| 1682   EmitBranch(true_block, false_block, true_cond); | 1683   EmitBranch(true_block, false_block, true_cond); | 
| 1683 } | 1684 } | 
| 1684 | 1685 | 
| 1685 | 1686 | 
|  | 1687 Condition LCodeGen::EmitIsString(Register input, | 
|  | 1688                                  Register temp1, | 
|  | 1689                                  Label* is_not_string) { | 
|  | 1690   __ JumpIfSmi(input, is_not_string); | 
|  | 1691 | 
|  | 1692   Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 
|  | 1693 | 
|  | 1694   return cond; | 
|  | 1695 } | 
|  | 1696 | 
|  | 1697 | 
|  | 1698 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 
|  | 1699   Register reg = ToRegister(instr->InputAt(0)); | 
|  | 1700   Register temp = ToRegister(instr->TempAt(0)); | 
|  | 1701 | 
|  | 1702   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 
|  | 1703   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 
|  | 1704   Label* false_label = chunk_->GetAssemblyLabel(false_block); | 
|  | 1705 | 
|  | 1706   Condition true_cond = EmitIsString(reg, temp, false_label); | 
|  | 1707 | 
|  | 1708   EmitBranch(true_block, false_block, true_cond); | 
|  | 1709 } | 
|  | 1710 | 
|  | 1711 | 
| 1686 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1712 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 
| 1687   Operand input = ToOperand(instr->InputAt(0)); | 1713   Operand input = ToOperand(instr->InputAt(0)); | 
| 1688 | 1714 | 
| 1689   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1715   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 
| 1690   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1716   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 
| 1691 | 1717 | 
| 1692   __ test(input, Immediate(kSmiTagMask)); | 1718   __ test(input, Immediate(kSmiTagMask)); | 
| 1693   EmitBranch(true_block, false_block, zero); | 1719   EmitBranch(true_block, false_block, zero); | 
| 1694 } | 1720 } | 
| 1695 | 1721 | 
| 1696 | 1722 | 
| 1697 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1723 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 
| 1698   Register input = ToRegister(instr->InputAt(0)); | 1724   Register input = ToRegister(instr->InputAt(0)); | 
| 1699   Register temp = ToRegister(instr->TempAt(0)); | 1725   Register temp = ToRegister(instr->TempAt(0)); | 
| 1700 | 1726 | 
| 1701   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1727   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 
| 1702   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1728   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 
| 1703 | 1729 | 
| 1704   STATIC_ASSERT(kSmiTag == 0); | 1730   STATIC_ASSERT(kSmiTag == 0); | 
| 1705   __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1731   __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 
| 1706   __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 1732   __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 
| 1707   __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 1733   __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 
| 1708             1 << Map::kIsUndetectable); | 1734             1 << Map::kIsUndetectable); | 
| 1709   EmitBranch(true_block, false_block, not_zero); | 1735   EmitBranch(true_block, false_block, not_zero); | 
| 1710 } | 1736 } | 
| 1711 | 1737 | 
| 1712 | 1738 | 
|  | 1739 static Condition ComputeCompareCondition(Token::Value op) { | 
|  | 1740   switch (op) { | 
|  | 1741     case Token::EQ_STRICT: | 
|  | 1742     case Token::EQ: | 
|  | 1743       return equal; | 
|  | 1744     case Token::LT: | 
|  | 1745       return less; | 
|  | 1746     case Token::GT: | 
|  | 1747       return greater; | 
|  | 1748     case Token::LTE: | 
|  | 1749       return less_equal; | 
|  | 1750     case Token::GTE: | 
|  | 1751       return greater_equal; | 
|  | 1752     default: | 
|  | 1753       UNREACHABLE(); | 
|  | 1754       return no_condition; | 
|  | 1755   } | 
|  | 1756 } | 
|  | 1757 | 
|  | 1758 | 
|  | 1759 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 
|  | 1760   Token::Value op = instr->op(); | 
|  | 1761   int true_block = chunk_->LookupDestination(instr->true_block_id()); | 
|  | 1762   int false_block = chunk_->LookupDestination(instr->false_block_id()); | 
|  | 1763 | 
|  | 1764   Handle<Code> ic = CompareIC::GetUninitialized(op); | 
|  | 1765   CallCode(ic, RelocInfo::CODE_TARGET, instr); | 
|  | 1766 | 
|  | 1767   Condition condition = ComputeCompareCondition(op); | 
|  | 1768   __ test(eax, Operand(eax)); | 
|  | 1769 | 
|  | 1770   EmitBranch(true_block, false_block, condition); | 
|  | 1771 } | 
|  | 1772 | 
|  | 1773 | 
| 1713 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 1774 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 
| 1714   InstanceType from = instr->from(); | 1775   InstanceType from = instr->from(); | 
| 1715   InstanceType to = instr->to(); | 1776   InstanceType to = instr->to(); | 
| 1716   if (from == FIRST_TYPE) return to; | 1777   if (from == FIRST_TYPE) return to; | 
| 1717   ASSERT(from == to || to == LAST_TYPE); | 1778   ASSERT(from == to || to == LAST_TYPE); | 
| 1718   return from; | 1779   return from; | 
| 1719 } | 1780 } | 
| 1720 | 1781 | 
| 1721 | 1782 | 
| 1722 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 1783 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1980                   RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2041                   RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 
| 1981   ASSERT(instr->HasDeoptimizationEnvironment()); | 2042   ASSERT(instr->HasDeoptimizationEnvironment()); | 
| 1982   LEnvironment* env = instr->deoptimization_environment(); | 2043   LEnvironment* env = instr->deoptimization_environment(); | 
| 1983   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2044   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 
| 1984 | 2045 | 
| 1985   // Put the result value into the eax slot and restore all registers. | 2046   // Put the result value into the eax slot and restore all registers. | 
| 1986   __ StoreToSafepointRegisterSlot(eax, eax); | 2047   __ StoreToSafepointRegisterSlot(eax, eax); | 
| 1987 } | 2048 } | 
| 1988 | 2049 | 
| 1989 | 2050 | 
| 1990 static Condition ComputeCompareCondition(Token::Value op) { |  | 
| 1991   switch (op) { |  | 
| 1992     case Token::EQ_STRICT: |  | 
| 1993     case Token::EQ: |  | 
| 1994       return equal; |  | 
| 1995     case Token::LT: |  | 
| 1996       return less; |  | 
| 1997     case Token::GT: |  | 
| 1998       return greater; |  | 
| 1999     case Token::LTE: |  | 
| 2000       return less_equal; |  | 
| 2001     case Token::GTE: |  | 
| 2002       return greater_equal; |  | 
| 2003     default: |  | 
| 2004       UNREACHABLE(); |  | 
| 2005       return no_condition; |  | 
| 2006   } |  | 
| 2007 } |  | 
| 2008 |  | 
| 2009 |  | 
| 2010 void LCodeGen::DoCmpT(LCmpT* instr) { | 2051 void LCodeGen::DoCmpT(LCmpT* instr) { | 
| 2011   Token::Value op = instr->op(); | 2052   Token::Value op = instr->op(); | 
| 2012 | 2053 | 
| 2013   Handle<Code> ic = CompareIC::GetUninitialized(op); | 2054   Handle<Code> ic = CompareIC::GetUninitialized(op); | 
| 2014   CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2055   CallCode(ic, RelocInfo::CODE_TARGET, instr); | 
| 2015 | 2056 | 
| 2016   Condition condition = ComputeCompareCondition(op); | 2057   Condition condition = ComputeCompareCondition(op); | 
| 2017   Label true_value, done; | 2058   Label true_value, done; | 
| 2018   __ test(eax, Operand(eax)); | 2059   __ test(eax, Operand(eax)); | 
| 2019   __ j(condition, &true_value, Label::kNear); | 2060   __ j(condition, &true_value, Label::kNear); | 
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3364   class DeferredStringCharCodeAt: public LDeferredCode { | 3405   class DeferredStringCharCodeAt: public LDeferredCode { | 
| 3365    public: | 3406    public: | 
| 3366     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 3407     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 
| 3367         : LDeferredCode(codegen), instr_(instr) { } | 3408         : LDeferredCode(codegen), instr_(instr) { } | 
| 3368     virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 3409     virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 
| 3369     virtual LInstruction* instr() { return instr_; } | 3410     virtual LInstruction* instr() { return instr_; } | 
| 3370    private: | 3411    private: | 
| 3371     LStringCharCodeAt* instr_; | 3412     LStringCharCodeAt* instr_; | 
| 3372   }; | 3413   }; | 
| 3373 | 3414 | 
| 3374   Register string = ToRegister(instr->string()); |  | 
| 3375   Register index = ToRegister(instr->index()); |  | 
| 3376   Register result = ToRegister(instr->result()); |  | 
| 3377 |  | 
| 3378   DeferredStringCharCodeAt* deferred = | 3415   DeferredStringCharCodeAt* deferred = | 
| 3379       new DeferredStringCharCodeAt(this, instr); | 3416       new DeferredStringCharCodeAt(this, instr); | 
| 3380 | 3417 | 
| 3381   // Fetch the instance type of the receiver into result register. | 3418   StringCharLoadGenerator::Generate(masm(), | 
| 3382   __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 3419                                     factory(), | 
| 3383   __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3420                                     ToRegister(instr->string()), | 
| 3384 | 3421                                     ToRegister(instr->index()), | 
| 3385   // We need special handling for indirect strings. | 3422                                     ToRegister(instr->result()), | 
| 3386   Label check_sequential; | 3423                                     deferred->entry()); | 
| 3387   __ test(result, Immediate(kIsIndirectStringMask)); |  | 
| 3388   __ j(zero, &check_sequential, Label::kNear); |  | 
| 3389 |  | 
| 3390   // Dispatch on the indirect string shape: slice or cons. |  | 
| 3391   Label cons_string; |  | 
| 3392   __ test(result, Immediate(kSlicedNotConsMask)); |  | 
| 3393   __ j(zero, &cons_string, Label::kNear); |  | 
| 3394 |  | 
| 3395   // Handle slices. |  | 
| 3396   Label indirect_string_loaded; |  | 
| 3397   __ mov(result, FieldOperand(string, SlicedString::kOffsetOffset)); |  | 
| 3398   __ SmiUntag(result); |  | 
| 3399   __ add(index, Operand(result)); |  | 
| 3400   __ mov(string, FieldOperand(string, SlicedString::kParentOffset)); |  | 
| 3401   __ jmp(&indirect_string_loaded, Label::kNear); |  | 
| 3402 |  | 
| 3403   // Handle conses. |  | 
| 3404   // Check whether the right hand side is the empty string (i.e. if |  | 
| 3405   // this is really a flat string in a cons string). If that is not |  | 
| 3406   // the case we would rather go to the runtime system now to flatten |  | 
| 3407   // the string. |  | 
| 3408   __ bind(&cons_string); |  | 
| 3409   __ cmp(FieldOperand(string, ConsString::kSecondOffset), |  | 
| 3410          Immediate(factory()->empty_string())); |  | 
| 3411   __ j(not_equal, deferred->entry()); |  | 
| 3412   __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); |  | 
| 3413 |  | 
| 3414   __ bind(&indirect_string_loaded); |  | 
| 3415   __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |  | 
| 3416   __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |  | 
| 3417 |  | 
| 3418   // Check whether the string is sequential. The only non-sequential |  | 
| 3419   // shapes we support have just been unwrapped above. |  | 
| 3420   // Note that if the original string is a cons or slice with an external |  | 
| 3421   // string as underlying string, we pass that unpacked underlying string with |  | 
| 3422   // the adjusted index to the runtime function. |  | 
| 3423   __ bind(&check_sequential); |  | 
| 3424   STATIC_ASSERT(kSeqStringTag == 0); |  | 
| 3425   __ test(result, Immediate(kStringRepresentationMask)); |  | 
| 3426   __ j(not_zero, deferred->entry()); |  | 
| 3427 |  | 
| 3428   // Dispatch on the encoding: ASCII or two-byte. |  | 
| 3429   Label ascii_string; |  | 
| 3430   STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |  | 
| 3431   STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |  | 
| 3432   __ test(result, Immediate(kStringEncodingMask)); |  | 
| 3433   __ j(not_zero, &ascii_string, Label::kNear); |  | 
| 3434 |  | 
| 3435   // Two-byte string. |  | 
| 3436   // Load the two-byte character code into the result register. |  | 
| 3437   Label done; |  | 
| 3438   STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |  | 
| 3439   __ movzx_w(result, FieldOperand(string, |  | 
| 3440                                   index, |  | 
| 3441                                   times_2, |  | 
| 3442                                   SeqTwoByteString::kHeaderSize)); |  | 
| 3443   __ jmp(&done, Label::kNear); |  | 
| 3444 |  | 
| 3445   // ASCII string. |  | 
| 3446   // Load the byte into the result register. |  | 
| 3447   __ bind(&ascii_string); |  | 
| 3448   __ movzx_b(result, FieldOperand(string, |  | 
| 3449                                   index, |  | 
| 3450                                   times_1, |  | 
| 3451                                   SeqAsciiString::kHeaderSize)); |  | 
| 3452   __ bind(&done); |  | 
| 3453   __ bind(deferred->exit()); | 3424   __ bind(deferred->exit()); | 
| 3454 } | 3425 } | 
| 3455 | 3426 | 
| 3456 | 3427 | 
| 3457 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 3428 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 
| 3458   Register string = ToRegister(instr->string()); | 3429   Register string = ToRegister(instr->string()); | 
| 3459   Register result = ToRegister(instr->result()); | 3430   Register result = ToRegister(instr->result()); | 
| 3460 | 3431 | 
| 3461   // TODO(3095996): Get rid of this. For now, we need to make the | 3432   // TODO(3095996): Get rid of this. For now, we need to make the | 
| 3462   // result register contain a valid pointer because it is already | 3433   // result register contain a valid pointer because it is already | 
| (...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4570       this, pointers, Safepoint::kLazyDeopt); | 4541       this, pointers, Safepoint::kLazyDeopt); | 
| 4571   __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4542   __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 
| 4572 } | 4543 } | 
| 4573 | 4544 | 
| 4574 | 4545 | 
| 4575 #undef __ | 4546 #undef __ | 
| 4576 | 4547 | 
| 4577 } }  // namespace v8::internal | 4548 } }  // namespace v8::internal | 
| 4578 | 4549 | 
| 4579 #endif  // V8_TARGET_ARCH_IA32 | 4550 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW | 
|---|