| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, | 49 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
| 50 "Huge method cutoff in unoptimized code size (in bytes)."); | 50 "Huge method cutoff in unoptimized code size (in bytes)."); |
| 51 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, | 51 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, |
| 52 "Huge method cutoff in tokens: Disables optimizations for huge methods."); | 52 "Huge method cutoff in tokens: Disables optimizations for huge methods."); |
| 53 DEFINE_FLAG(bool, overlap_type_arguments, true, | 53 DEFINE_FLAG(bool, overlap_type_arguments, true, |
| 54 "When possible, partially or fully overlap the type arguments of a type " | 54 "When possible, partially or fully overlap the type arguments of a type " |
| 55 "with the type arguments of its super type."); | 55 "with the type arguments of its super type."); |
| 56 DEFINE_FLAG(bool, show_internal_names, false, | 56 DEFINE_FLAG(bool, show_internal_names, false, |
| 57 "Show names of internal classes (e.g. \"OneByteString\") in error messages " | 57 "Show names of internal classes (e.g. \"OneByteString\") in error messages " |
| 58 "instead of showing the corresponding interface names (e.g. \"String\")"); | 58 "instead of showing the corresponding interface names (e.g. \"String\")"); |
| 59 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, | |
| 60 "Throw an exception when the result of an integer calculation will not " | |
| 61 "fit into a javascript integer."); | |
| 62 DEFINE_FLAG(bool, trace_cha, false, "Trace CHA operations"); | 59 DEFINE_FLAG(bool, trace_cha, false, "Trace CHA operations"); |
| 63 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids."); | 60 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids."); |
| 64 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache"); | 61 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache"); |
| 65 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids."); | 62 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids."); |
| 66 DEFINE_FLAG(bool, ignore_patch_signature_mismatch, false, | 63 DEFINE_FLAG(bool, ignore_patch_signature_mismatch, false, |
| 67 "Ignore patch file member signature mismatch."); | 64 "Ignore patch file member signature mismatch."); |
| 68 | 65 |
| 69 DECLARE_FLAG(charp, coverage_dir); | 66 DECLARE_FLAG(charp, coverage_dir); |
| 70 DECLARE_FLAG(bool, load_deferred_eagerly); | 67 DECLARE_FLAG(bool, load_deferred_eagerly); |
| 71 DECLARE_FLAG(bool, precompilation); | 68 DECLARE_FLAG(bool, precompilation); |
| (...skipping 11666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11738 } | 11735 } |
| 11739 | 11736 |
| 11740 | 11737 |
| 11741 void ICData::AddDeoptReason(DeoptReasonId reason) const { | 11738 void ICData::AddDeoptReason(DeoptReasonId reason) const { |
| 11742 if (reason <= kLastRecordedDeoptReason) { | 11739 if (reason <= kLastRecordedDeoptReason) { |
| 11743 SetDeoptReasons(DeoptReasons() | (1 << reason)); | 11740 SetDeoptReasons(DeoptReasons() | (1 << reason)); |
| 11744 } | 11741 } |
| 11745 } | 11742 } |
| 11746 | 11743 |
| 11747 | 11744 |
| 11748 bool ICData::IssuedJSWarning() const { | |
| 11749 return IssuedJSWarningBit::decode(raw_ptr()->state_bits_); | |
| 11750 } | |
| 11751 | |
| 11752 | |
| 11753 void ICData::SetIssuedJSWarning() const { | |
| 11754 StoreNonPointer(&raw_ptr()->state_bits_, | |
| 11755 IssuedJSWarningBit::update(true, raw_ptr()->state_bits_)); | |
| 11756 } | |
| 11757 | |
| 11758 | |
| 11759 bool ICData::MayCheckForJSWarning() const { | |
| 11760 const String& name = String::Handle(target_name()); | |
| 11761 // Warning issued from native code. | |
| 11762 // Calling sequence is decoded to obtain ic data in order to check if a | |
| 11763 // warning has already been issued. | |
| 11764 if (name.Equals(Library::PrivateCoreLibName(Symbols::_instanceOf())) || | |
| 11765 name.Equals(Library::PrivateCoreLibName(Symbols::_as()))) { | |
| 11766 return true; | |
| 11767 } | |
| 11768 // Warning issued in ic miss handler. | |
| 11769 // No decoding necessary, so allow optimization if warning already issued. | |
| 11770 if (name.Equals(Symbols::toString()) && !IssuedJSWarning()) { | |
| 11771 return true; | |
| 11772 } | |
| 11773 return false; | |
| 11774 } | |
| 11775 | |
| 11776 | |
| 11777 void ICData::set_state_bits(uint32_t bits) const { | 11745 void ICData::set_state_bits(uint32_t bits) const { |
| 11778 StoreNonPointer(&raw_ptr()->state_bits_, bits); | 11746 StoreNonPointer(&raw_ptr()->state_bits_, bits); |
| 11779 } | 11747 } |
| 11780 | 11748 |
| 11781 | 11749 |
| 11782 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { | 11750 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { |
| 11783 return num_args + 1 /* target function*/ + 1 /* frequency */; | 11751 return num_args + 1 /* target function*/ + 1 /* frequency */; |
| 11784 } | 11752 } |
| 11785 | 11753 |
| 11786 | 11754 |
| (...skipping 5117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16904 } | 16872 } |
| 16905 | 16873 |
| 16906 | 16874 |
| 16907 const char* Integer::ToCString() const { | 16875 const char* Integer::ToCString() const { |
| 16908 // Integer is an interface. No instances of Integer should exist except null. | 16876 // Integer is an interface. No instances of Integer should exist except null. |
| 16909 ASSERT(IsNull()); | 16877 ASSERT(IsNull()); |
| 16910 return "NULL Integer"; | 16878 return "NULL Integer"; |
| 16911 } | 16879 } |
| 16912 | 16880 |
| 16913 | 16881 |
| 16914 // Throw JavascriptIntegerOverflow exception. | |
| 16915 static void ThrowJavascriptIntegerOverflow(const Integer& i) { | |
| 16916 const Array& exc_args = Array::Handle(Array::New(1)); | |
| 16917 const String& i_str = String::Handle(String::New(i.ToCString())); | |
| 16918 exc_args.SetAt(0, i_str); | |
| 16919 Exceptions::ThrowByType(Exceptions::kJavascriptIntegerOverflowError, | |
| 16920 exc_args); | |
| 16921 } | |
| 16922 | |
| 16923 | |
| 16924 RawInteger* Integer::New(const String& str, Heap::Space space) { | 16882 RawInteger* Integer::New(const String& str, Heap::Space space) { |
| 16925 // We are not supposed to have integers represented as two byte strings. | 16883 // We are not supposed to have integers represented as two byte strings. |
| 16926 ASSERT(str.IsOneByteString()); | 16884 ASSERT(str.IsOneByteString()); |
| 16927 int64_t value; | 16885 int64_t value; |
| 16928 if (!OS::StringToInt64(str.ToCString(), &value)) { | 16886 if (!OS::StringToInt64(str.ToCString(), &value)) { |
| 16929 const Bigint& big = Bigint::Handle( | 16887 const Bigint& big = Bigint::Handle( |
| 16930 Bigint::NewFromCString(str.ToCString(), space)); | 16888 Bigint::NewFromCString(str.ToCString(), space)); |
| 16931 ASSERT(!big.FitsIntoSmi()); | 16889 ASSERT(!big.FitsIntoSmi()); |
| 16932 ASSERT(!big.FitsIntoInt64()); | 16890 ASSERT(!big.FitsIntoInt64()); |
| 16933 if (FLAG_throw_on_javascript_int_overflow) { | |
| 16934 ThrowJavascriptIntegerOverflow(big); | |
| 16935 } | |
| 16936 return big.raw(); | 16891 return big.raw(); |
| 16937 } | 16892 } |
| 16938 return Integer::New(value, space); | 16893 return Integer::New(value, space); |
| 16939 } | 16894 } |
| 16940 | 16895 |
| 16941 | 16896 |
| 16942 // This is called from LiteralToken::New() in the parser, so we can't | |
| 16943 // raise an exception for javascript overflow here. Instead we do it in | |
| 16944 // Parser::CurrentIntegerLiteral(), which is the point in the parser where | |
| 16945 // integer literals escape, so we can call Parser::ErrorMsg(). | |
| 16946 RawInteger* Integer::NewCanonical(const String& str) { | 16897 RawInteger* Integer::NewCanonical(const String& str) { |
| 16947 // We are not supposed to have integers represented as two byte strings. | 16898 // We are not supposed to have integers represented as two byte strings. |
| 16948 ASSERT(str.IsOneByteString()); | 16899 ASSERT(str.IsOneByteString()); |
| 16949 int64_t value; | 16900 int64_t value; |
| 16950 if (!OS::StringToInt64(str.ToCString(), &value)) { | 16901 if (!OS::StringToInt64(str.ToCString(), &value)) { |
| 16951 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); | 16902 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); |
| 16952 ASSERT(!big.FitsIntoSmi()); | 16903 ASSERT(!big.FitsIntoSmi()); |
| 16953 ASSERT(!big.FitsIntoInt64()); | 16904 ASSERT(!big.FitsIntoInt64()); |
| 16954 return big.raw(); | 16905 return big.raw(); |
| 16955 } | 16906 } |
| 16956 if (Smi::IsValid(value)) { | 16907 if (Smi::IsValid(value)) { |
| 16957 return Smi::New(static_cast<intptr_t>(value)); | 16908 return Smi::New(static_cast<intptr_t>(value)); |
| 16958 } | 16909 } |
| 16959 return Mint::NewCanonical(value); | 16910 return Mint::NewCanonical(value); |
| 16960 } | 16911 } |
| 16961 | 16912 |
| 16962 | 16913 |
| 16963 RawInteger* Integer::New(int64_t value, Heap::Space space, const bool silent) { | 16914 RawInteger* Integer::New(int64_t value, Heap::Space space) { |
| 16964 const bool is_smi = Smi::IsValid(value); | 16915 const bool is_smi = Smi::IsValid(value); |
| 16965 if (!silent && | |
| 16966 FLAG_throw_on_javascript_int_overflow && | |
| 16967 !Utils::IsJavascriptInt(value)) { | |
| 16968 const Integer& i = is_smi ? | |
| 16969 Integer::Handle(Smi::New(static_cast<intptr_t>(value))) : | |
| 16970 Integer::Handle(Mint::New(value, space)); | |
| 16971 ThrowJavascriptIntegerOverflow(i); | |
| 16972 } | |
| 16973 if (is_smi) { | 16916 if (is_smi) { |
| 16974 return Smi::New(static_cast<intptr_t>(value)); | 16917 return Smi::New(static_cast<intptr_t>(value)); |
| 16975 } | 16918 } |
| 16976 return Mint::New(value, space); | 16919 return Mint::New(value, space); |
| 16977 } | 16920 } |
| 16978 | 16921 |
| 16979 | 16922 |
| 16980 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { | 16923 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { |
| 16981 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { | 16924 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { |
| 16982 if (FLAG_throw_on_javascript_int_overflow) { | |
| 16983 const Integer &i = Integer::Handle(Bigint::NewFromUint64(value, space)); | |
| 16984 ThrowJavascriptIntegerOverflow(i); | |
| 16985 } | |
| 16986 return Bigint::NewFromUint64(value, space); | 16925 return Bigint::NewFromUint64(value, space); |
| 16987 } else { | 16926 } else { |
| 16988 return Integer::New(value, space); | 16927 return Integer::New(value, space); |
| 16989 } | 16928 } |
| 16990 } | 16929 } |
| 16991 | 16930 |
| 16992 | 16931 |
| 16993 bool Integer::Equals(const Instance& other) const { | 16932 bool Integer::Equals(const Instance& other) const { |
| 16994 // Integer is an abstract class. | 16933 // Integer is an abstract class. |
| 16995 UNREACHABLE(); | 16934 UNREACHABLE(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17039 } | 16978 } |
| 17040 | 16979 |
| 17041 | 16980 |
| 17042 int Integer::CompareWith(const Integer& other) const { | 16981 int Integer::CompareWith(const Integer& other) const { |
| 17043 // Integer is an abstract class. | 16982 // Integer is an abstract class. |
| 17044 UNREACHABLE(); | 16983 UNREACHABLE(); |
| 17045 return 0; | 16984 return 0; |
| 17046 } | 16985 } |
| 17047 | 16986 |
| 17048 | 16987 |
| 17049 // Returns true if the signed Integer does not fit into a | |
| 17050 // Javascript integer. | |
| 17051 bool Integer::CheckJavascriptIntegerOverflow() const { | |
| 17052 // Always overflow if the value doesn't fit into an int64_t. | |
| 17053 int64_t value = 1ULL << 63; | |
| 17054 if (IsSmi()) { | |
| 17055 value = AsInt64Value(); | |
| 17056 } else if (IsMint()) { | |
| 17057 Mint& mint = Mint::Handle(); | |
| 17058 mint ^= raw(); | |
| 17059 value = mint.value(); | |
| 17060 } else { | |
| 17061 if (Bigint::Cast(*this).FitsIntoInt64()) { | |
| 17062 value = AsInt64Value(); | |
| 17063 } | |
| 17064 } | |
| 17065 return !Utils::IsJavascriptInt(value); | |
| 17066 } | |
| 17067 | |
| 17068 | |
| 17069 RawInteger* Integer::AsValidInteger() const { | 16988 RawInteger* Integer::AsValidInteger() const { |
| 17070 if (FLAG_throw_on_javascript_int_overflow && | |
| 17071 CheckJavascriptIntegerOverflow()) { | |
| 17072 ThrowJavascriptIntegerOverflow(*this); | |
| 17073 } | |
| 17074 if (IsSmi()) return raw(); | 16989 if (IsSmi()) return raw(); |
| 17075 if (IsMint()) { | 16990 if (IsMint()) { |
| 17076 Mint& mint = Mint::Handle(); | 16991 Mint& mint = Mint::Handle(); |
| 17077 mint ^= raw(); | 16992 mint ^= raw(); |
| 17078 if (Smi::IsValid(mint.value())) { | 16993 if (Smi::IsValid(mint.value())) { |
| 17079 return Smi::New(static_cast<intptr_t>(mint.value())); | 16994 return Smi::New(static_cast<intptr_t>(mint.value())); |
| 17080 } else { | 16995 } else { |
| 17081 return raw(); | 16996 return raw(); |
| 17082 } | 16997 } |
| 17083 } | 16998 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17233 UNIMPLEMENTED(); | 17148 UNIMPLEMENTED(); |
| 17234 } | 17149 } |
| 17235 } | 17150 } |
| 17236 return Integer::null(); // Notify caller that a bigint operation is required. | 17151 return Integer::null(); // Notify caller that a bigint operation is required. |
| 17237 } | 17152 } |
| 17238 | 17153 |
| 17239 | 17154 |
| 17240 // TODO(srdjan): Clarify handling of negative right operand in a shift op. | 17155 // TODO(srdjan): Clarify handling of negative right operand in a shift op. |
| 17241 RawInteger* Smi::ShiftOp(Token::Kind kind, | 17156 RawInteger* Smi::ShiftOp(Token::Kind kind, |
| 17242 const Smi& other, | 17157 const Smi& other, |
| 17243 Heap::Space space, | 17158 Heap::Space space) const { |
| 17244 const bool silent) const { | |
| 17245 intptr_t result = 0; | 17159 intptr_t result = 0; |
| 17246 const intptr_t left_value = Value(); | 17160 const intptr_t left_value = Value(); |
| 17247 const intptr_t right_value = other.Value(); | 17161 const intptr_t right_value = other.Value(); |
| 17248 ASSERT(right_value >= 0); | 17162 ASSERT(right_value >= 0); |
| 17249 switch (kind) { | 17163 switch (kind) { |
| 17250 case Token::kSHL: { | 17164 case Token::kSHL: { |
| 17251 if ((left_value == 0) || (right_value == 0)) { | 17165 if ((left_value == 0) || (right_value == 0)) { |
| 17252 return raw(); | 17166 return raw(); |
| 17253 } | 17167 } |
| 17254 { // Check for overflow. | 17168 { // Check for overflow. |
| 17255 int cnt = Utils::BitLength(left_value); | 17169 int cnt = Utils::BitLength(left_value); |
| 17256 if ((cnt + right_value) > Smi::kBits) { | 17170 if ((cnt + right_value) > Smi::kBits) { |
| 17257 if ((cnt + right_value) > Mint::kBits) { | 17171 if ((cnt + right_value) > Mint::kBits) { |
| 17258 return Bigint::NewFromShiftedInt64(left_value, right_value, space); | 17172 return Bigint::NewFromShiftedInt64(left_value, right_value, space); |
| 17259 } else { | 17173 } else { |
| 17260 int64_t left_64 = left_value; | 17174 int64_t left_64 = left_value; |
| 17261 return Integer::New(left_64 << right_value, space, silent); | 17175 return Integer::New(left_64 << right_value, space); |
| 17262 } | 17176 } |
| 17263 } | 17177 } |
| 17264 } | 17178 } |
| 17265 result = left_value << right_value; | 17179 result = left_value << right_value; |
| 17266 break; | 17180 break; |
| 17267 } | 17181 } |
| 17268 case Token::kSHR: { | 17182 case Token::kSHR: { |
| 17269 const intptr_t shift_amount = | 17183 const intptr_t shift_amount = |
| 17270 (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value; | 17184 (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value; |
| 17271 result = left_value >> shift_amount; | 17185 result = left_value >> shift_amount; |
| (...skipping 4220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21492 return UserTag::null(); | 21406 return UserTag::null(); |
| 21493 } | 21407 } |
| 21494 | 21408 |
| 21495 | 21409 |
| 21496 const char* UserTag::ToCString() const { | 21410 const char* UserTag::ToCString() const { |
| 21497 const String& tag_label = String::Handle(label()); | 21411 const String& tag_label = String::Handle(label()); |
| 21498 return tag_label.ToCString(); | 21412 return tag_label.ToCString(); |
| 21499 } | 21413 } |
| 21500 | 21414 |
| 21501 } // namespace dart | 21415 } // namespace dart |
| OLD | NEW |