Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1944 __ cmpl(ESP, | 1944 __ cmpl(ESP, |
| 1945 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1945 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 1946 __ j(BELOW_EQUAL, slow_path->entry_label()); | 1946 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 1947 __ Bind(slow_path->exit_label()); | 1947 __ Bind(slow_path->exit_label()); |
| 1948 } | 1948 } |
| 1949 | 1949 |
| 1950 | 1950 |
| 1951 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { | 1951 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 1952 const intptr_t kNumInputs = 2; | 1952 const intptr_t kNumInputs = 2; |
| 1953 if (op_kind() == Token::kTRUNCDIV) { | 1953 if (op_kind() == Token::kTRUNCDIV) { |
| 1954 const intptr_t kNumTemps = 1; | 1954 const intptr_t kNumTemps = RightIsPowerOfTwoConstant() ? 2 : 1; |
| 1955 LocationSummary* summary = | 1955 LocationSummary* summary = |
| 1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1957 // Both inputs must be writable because they will be untagged. | 1957 // Both inputs must be writable because they will be untagged. |
| 1958 summary->set_in(0, Location::RegisterLocation(EAX)); | 1958 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1959 summary->set_in(1, Location::WritableRegister()); | 1959 if (kNumTemps == 1) { |
| 1960 summary->set_in(1, Location::WritableRegister()); | |
| 1961 } else { | |
| 1962 ConstantInstr* right_constant = right()->definition()->AsConstant(); | |
| 1963 summary->set_in(1, Location::Constant(right_constant->value())); | |
| 1964 // Temporary to hold divisor constant. | |
| 1965 summary->set_temp(1, Location::RegisterLocation(EBX)); | |
| 1966 } | |
| 1960 summary->set_out(Location::SameAsFirstInput()); | 1967 summary->set_out(Location::SameAsFirstInput()); |
| 1961 // Will be used for sign extension and division. | 1968 // Will be used for sign extension and division. |
| 1962 summary->set_temp(0, Location::RegisterLocation(EDX)); | 1969 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 1963 return summary; | 1970 return summary; |
| 1964 } else if (op_kind() == Token::kSHR) { | 1971 } else if (op_kind() == Token::kSHR) { |
| 1965 const intptr_t kNumTemps = 0; | 1972 const intptr_t kNumTemps = 0; |
| 1966 LocationSummary* summary = | 1973 LocationSummary* summary = |
| 1967 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1974 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1968 summary->set_in(0, Location::RequiresRegister()); | 1975 summary->set_in(0, Location::RequiresRegister()); |
| 1969 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 1976 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1989 } | 1996 } |
| 1990 } | 1997 } |
| 1991 | 1998 |
| 1992 | 1999 |
| 1993 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2000 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1994 Register left = locs()->in(0).reg(); | 2001 Register left = locs()->in(0).reg(); |
| 1995 Register result = locs()->out().reg(); | 2002 Register result = locs()->out().reg(); |
| 1996 ASSERT(left == result); | 2003 ASSERT(left == result); |
| 1997 Label* deopt = NULL; | 2004 Label* deopt = NULL; |
| 1998 if (CanDeoptimize()) { | 2005 if (CanDeoptimize()) { |
| 1999 deopt = compiler->AddDeoptStub(deopt_id(), | 2006 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 2000 kDeoptBinarySmiOp); | |
| 2001 } | 2007 } |
| 2002 | 2008 |
| 2003 if (locs()->in(1).IsConstant()) { | 2009 if (locs()->in(1).IsConstant()) { |
| 2004 const Object& constant = locs()->in(1).constant(); | 2010 const Object& constant = locs()->in(1).constant(); |
| 2005 ASSERT(constant.IsSmi()); | 2011 ASSERT(constant.IsSmi()); |
| 2006 const int32_t imm = | 2012 const int32_t imm = |
| 2007 reinterpret_cast<int32_t>(constant.raw()); | 2013 reinterpret_cast<int32_t>(constant.raw()); |
| 2008 switch (op_kind()) { | 2014 switch (op_kind()) { |
| 2009 case Token::kADD: | 2015 case Token::kADD: |
| 2010 __ addl(left, Immediate(imm)); | 2016 __ addl(left, Immediate(imm)); |
| 2011 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2017 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2012 break; | 2018 break; |
| 2013 case Token::kSUB: { | 2019 case Token::kSUB: { |
| 2014 __ subl(left, Immediate(imm)); | 2020 __ subl(left, Immediate(imm)); |
| 2015 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2021 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2016 break; | 2022 break; |
| 2017 } | 2023 } |
| 2018 case Token::kMUL: { | 2024 case Token::kMUL: { |
| 2019 // Keep left value tagged and untag right value. | 2025 // Keep left value tagged and untag right value. |
| 2020 const intptr_t value = Smi::Cast(constant).Value(); | 2026 const intptr_t value = Smi::Cast(constant).Value(); |
| 2021 __ imull(left, Immediate(value)); | 2027 __ imull(left, Immediate(value)); |
| 2022 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2028 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2023 break; | 2029 break; |
| 2024 } | 2030 } |
| 2031 case Token::kTRUNCDIV: { | |
| 2032 Label use_div, done; | |
| 2033 const intptr_t value = Smi::Cast(constant).Value(); | |
| 2034 ASSERT((value > 0) && Utils::IsPowerOfTwo(value)); | |
| 2035 __ cmpl(left, Immediate(0)); | |
|
Florian Schneider
2013/02/01 11:48:33
For checking x < 0, this sequence is 1 byte shorte
| |
| 2036 __ j(LESS, &use_div, Assembler::kNearJump); | |
| 2037 // Positive division by power of two is an arithmetic left shift. | |
|
Florian Schneider
2013/02/01 11:48:33
In the comment s/left/right/.
srdjan
2013/02/01 22:57:54
Done.
| |
| 2038 intptr_t shift_count = Utils::ShiftForPowerOfTwo(value) + kSmiTagSize; | |
| 2039 __ sarl(left, Immediate(shift_count)); | |
| 2040 __ jmp(&done, Assembler::kNearJump); | |
| 2041 __ Bind(&use_div); | |
|
Florian Schneider
2013/02/01 11:48:33
I think this could be improved for negative number
Florian Schneider
2013/02/04 13:04:02
Yes, my mistake: of course the absolute value of r
| |
| 2042 Register right = locs()->temp(1).reg(); | |
| 2043 ASSERT(left == EAX); | |
| 2044 ASSERT((right != EDX) && (right != EAX)); | |
| 2045 ASSERT(locs()->temp(0).reg() == EDX); | |
| 2046 ASSERT(result == EAX); | |
| 2047 __ movl(right, Immediate(value)); | |
| 2048 __ SmiUntag(left); | |
| 2049 __ cdq(); // Sign extend EAX -> EDX:EAX. | |
| 2050 __ idivl(right); // EAX: quotient, EDX: remainder. | |
| 2051 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | |
|
Florian Schneider
2013/02/01 11:48:33
Since the right side is a known constant, you can
| |
| 2052 // case we cannot tag the result. | |
| 2053 __ cmpl(result, Immediate(0x40000000)); | |
| 2054 __ j(EQUAL, deopt); | |
| 2055 __ Bind(&done); | |
| 2056 __ SmiTag(result); | |
| 2057 break; | |
| 2058 } | |
| 2025 case Token::kBIT_AND: { | 2059 case Token::kBIT_AND: { |
| 2026 // No overflow check. | 2060 // No overflow check. |
| 2027 __ andl(left, Immediate(imm)); | 2061 __ andl(left, Immediate(imm)); |
| 2028 break; | 2062 break; |
| 2029 } | 2063 } |
| 2030 case Token::kBIT_OR: { | 2064 case Token::kBIT_OR: { |
| 2031 // No overflow check. | 2065 // No overflow check. |
| 2032 __ orl(left, Immediate(imm)); | 2066 __ orl(left, Immediate(imm)); |
| 2033 break; | 2067 break; |
| 2034 } | 2068 } |
| (...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3366 PcDescriptors::kOther, | 3400 PcDescriptors::kOther, |
| 3367 locs()); | 3401 locs()); |
| 3368 __ Drop(2); // Discard type arguments and receiver. | 3402 __ Drop(2); // Discard type arguments and receiver. |
| 3369 } | 3403 } |
| 3370 | 3404 |
| 3371 } // namespace dart | 3405 } // namespace dart |
| 3372 | 3406 |
| 3373 #undef __ | 3407 #undef __ |
| 3374 | 3408 |
| 3375 #endif // defined TARGET_ARCH_IA32 | 3409 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |