Chromium Code Reviews| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 DEFINE_FLAG(bool, show_internal_names, false, | 45 DEFINE_FLAG(bool, show_internal_names, false, |
| 46 "Show names of internal classes (e.g. \"OneByteString\") in error messages " | 46 "Show names of internal classes (e.g. \"OneByteString\") in error messages " |
| 47 "instead of showing the corresponding interface names (e.g. \"String\")"); | 47 "instead of showing the corresponding interface names (e.g. \"String\")"); |
| 48 DEFINE_FLAG(bool, trace_disabling_optimized_code, false, | 48 DEFINE_FLAG(bool, trace_disabling_optimized_code, false, |
| 49 "Trace disabling optimized code."); | 49 "Trace disabling optimized code."); |
| 50 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, | 50 DEFINE_FLAG(int, huge_method_cutoff_in_tokens, 20000, |
| 51 "Huge method cutoff in tokens: Disables optimizations for huge methods."); | 51 "Huge method cutoff in tokens: Disables optimizations for huge methods."); |
| 52 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, | 52 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
| 53 "Huge method cutoff in unoptimized code size (in bytes)."); | 53 "Huge method cutoff in unoptimized code size (in bytes)."); |
| 54 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, | 54 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, |
| 55 "Throw an exception when integer arithmetic exceeds 53 bits."); | 55 "Throw an exception when the result of an integer calculation will not " |
| 56 "fit into a javascript integer."); | |
| 56 DECLARE_FLAG(bool, trace_compiler); | 57 DECLARE_FLAG(bool, trace_compiler); |
| 57 DECLARE_FLAG(bool, eliminate_type_checks); | 58 DECLARE_FLAG(bool, eliminate_type_checks); |
| 58 DECLARE_FLAG(bool, enable_type_checks); | 59 DECLARE_FLAG(bool, enable_type_checks); |
| 59 | 60 |
| 60 static const char* kGetterPrefix = "get:"; | 61 static const char* kGetterPrefix = "get:"; |
| 61 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); | 62 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); |
| 62 static const char* kSetterPrefix = "set:"; | 63 static const char* kSetterPrefix = "set:"; |
| 63 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); | 64 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); |
| 64 | 65 |
| 65 cpp_vtable Object::handle_vtable_ = 0; | 66 cpp_vtable Object::handle_vtable_ = 0; |
| (...skipping 11160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11226 return "Integer"; | 11227 return "Integer"; |
| 11227 } | 11228 } |
| 11228 | 11229 |
| 11229 | 11230 |
| 11230 void Integer::PrintToJSONStream(JSONStream* stream, bool ref) const { | 11231 void Integer::PrintToJSONStream(JSONStream* stream, bool ref) const { |
| 11231 stream->OpenObject(); | 11232 stream->OpenObject(); |
| 11232 stream->CloseObject(); | 11233 stream->CloseObject(); |
| 11233 } | 11234 } |
| 11234 | 11235 |
| 11235 | 11236 |
| 11236 // Throw FiftyThreeBitOverflow exception. | 11237 // Throw JavascriptIntegerOverflow exception. |
| 11237 static void ThrowFiftyThreeBitOverflow(const Integer& i) { | 11238 static void ThrowJavascriptIntegerOverflow(const Integer& i) { |
| 11238 const Array& exc_args = Array::Handle(Array::New(1)); | 11239 const Array& exc_args = Array::Handle(Array::New(1)); |
| 11239 const String& i_str = String::Handle(String::New(i.ToCString())); | 11240 const String& i_str = String::Handle(String::New(i.ToCString())); |
| 11240 exc_args.SetAt(0, i_str); | 11241 exc_args.SetAt(0, i_str); |
| 11241 Exceptions::ThrowByType(Exceptions::kFiftyThreeBitOverflowError, exc_args); | 11242 Exceptions::ThrowByType(Exceptions::kJavascriptIntegerOverflowError, |
| 11243 exc_args); | |
| 11242 } | 11244 } |
| 11243 | 11245 |
| 11244 | 11246 |
| 11245 RawInteger* Integer::New(const String& str, Heap::Space space) { | 11247 RawInteger* Integer::New(const String& str, Heap::Space space) { |
| 11246 // We are not supposed to have integers represented as two byte strings. | 11248 // We are not supposed to have integers represented as two byte strings. |
| 11247 ASSERT(str.IsOneByteString()); | 11249 ASSERT(str.IsOneByteString()); |
| 11248 int64_t value; | 11250 int64_t value; |
| 11249 if (!OS::StringToInt64(str.ToCString(), &value)) { | 11251 if (!OS::StringToInt64(str.ToCString(), &value)) { |
| 11250 const Bigint& big = Bigint::Handle(Bigint::New(str, space)); | 11252 const Bigint& big = Bigint::Handle(Bigint::New(str, space)); |
| 11251 ASSERT(!BigintOperations::FitsIntoSmi(big)); | 11253 ASSERT(!BigintOperations::FitsIntoSmi(big)); |
| 11252 ASSERT(!BigintOperations::FitsIntoInt64(big)); | 11254 ASSERT(!BigintOperations::FitsIntoInt64(big)); |
| 11253 if (FLAG_throw_on_javascript_int_overflow) { | 11255 if (FLAG_throw_on_javascript_int_overflow) { |
| 11254 ThrowFiftyThreeBitOverflow(big); | 11256 ThrowJavascriptIntegerOverflow(big); |
| 11255 } | 11257 } |
| 11256 return big.raw(); | 11258 return big.raw(); |
| 11257 } | 11259 } |
| 11258 return Integer::New(value, space); | 11260 return Integer::New(value, space); |
| 11259 } | 11261 } |
| 11260 | 11262 |
| 11261 | 11263 |
| 11262 // This is called from LiteralToken::New() in the parser, so we can't | 11264 // This is called from LiteralToken::New() in the parser, so we can't |
| 11263 // raise an exception for 53-bit overflow here. Instead we do it in | 11265 // raise an exception for 54-bit overflow here. Instead we do it in |
| 11264 // Parser::CurrentIntegerLiteral(), which is the point in the parser where | 11266 // Parser::CurrentIntegerLiteral(), which is the point in the parser where |
| 11265 // integer literals escape, so we can call Parser::ErrorMsg(). | 11267 // integer literals escape, so we can call Parser::ErrorMsg(). |
| 11266 RawInteger* Integer::NewCanonical(const String& str) { | 11268 RawInteger* Integer::NewCanonical(const String& str) { |
| 11267 // We are not supposed to have integers represented as two byte strings. | 11269 // We are not supposed to have integers represented as two byte strings. |
| 11268 ASSERT(str.IsOneByteString()); | 11270 ASSERT(str.IsOneByteString()); |
| 11269 int64_t value; | 11271 int64_t value; |
| 11270 if (!OS::StringToInt64(str.ToCString(), &value)) { | 11272 if (!OS::StringToInt64(str.ToCString(), &value)) { |
| 11271 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); | 11273 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); |
| 11272 ASSERT(!BigintOperations::FitsIntoSmi(big)); | 11274 ASSERT(!BigintOperations::FitsIntoSmi(big)); |
| 11273 ASSERT(!BigintOperations::FitsIntoInt64(big)); | 11275 ASSERT(!BigintOperations::FitsIntoInt64(big)); |
| 11274 return big.raw(); | 11276 return big.raw(); |
| 11275 } | 11277 } |
| 11276 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) { | 11278 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) { |
| 11277 return Smi::New(value); | 11279 return Smi::New(value); |
| 11278 } | 11280 } |
| 11279 return Mint::NewCanonical(value); | 11281 return Mint::NewCanonical(value); |
| 11280 } | 11282 } |
| 11281 | 11283 |
| 11282 | 11284 |
| 11285 // dart2js represents integers as double precision floats. It does this using | |
| 11286 // a sign bit and 53 fraction bits. This gives us the range | |
| 11287 // -2^54 - 1 ... 2^54 - 1, i.e. the same as a 54-bit signed integer | |
|
Florian Schneider
2013/08/01 15:45:03
Something is slightly off here: a int54_t has a ra
| |
| 11288 // without the most negative number. Thus, here we check if the value is | |
| 11289 // a 54-bit signed integer and not -2^54 | |
| 11290 static bool Is54BitNoMinInt(int64_t value) { | |
| 11291 return (Utils::IsInt(54, value)) && (value != (-0x1FFFFFFFFFFFFF - 1)); | |
|
Florian Schneider
2013/08/02 10:24:17
I think this should be
return Utils::IsInt(54, va
| |
| 11292 } | |
| 11293 | |
| 11294 | |
| 11283 RawInteger* Integer::New(int64_t value, Heap::Space space) { | 11295 RawInteger* Integer::New(int64_t value, Heap::Space space) { |
| 11284 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) { | 11296 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) { |
| 11285 return Smi::New(value); | 11297 return Smi::New(value); |
| 11286 } | 11298 } |
| 11287 if (FLAG_throw_on_javascript_int_overflow && !Utils::IsInt(53, value)) { | 11299 if (FLAG_throw_on_javascript_int_overflow && !Is54BitNoMinInt(value)) { |
| 11288 const Integer &i = Integer::Handle(Mint::New(value)); | 11300 const Integer &i = Integer::Handle(Mint::New(value)); |
| 11289 ThrowFiftyThreeBitOverflow(i); | 11301 ThrowJavascriptIntegerOverflow(i); |
| 11290 } | 11302 } |
| 11291 return Mint::New(value, space); | 11303 return Mint::New(value, space); |
| 11292 } | 11304 } |
| 11293 | 11305 |
| 11294 | 11306 |
| 11295 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { | 11307 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { |
| 11296 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { | 11308 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { |
| 11297 if (FLAG_throw_on_javascript_int_overflow) { | 11309 if (FLAG_throw_on_javascript_int_overflow) { |
| 11298 const Integer &i = | 11310 const Integer &i = |
| 11299 Integer::Handle(BigintOperations::NewFromUint64(value)); | 11311 Integer::Handle(BigintOperations::NewFromUint64(value)); |
| 11300 ThrowFiftyThreeBitOverflow(i); | 11312 ThrowJavascriptIntegerOverflow(i); |
| 11301 } | 11313 } |
| 11302 return BigintOperations::NewFromUint64(value); | 11314 return BigintOperations::NewFromUint64(value); |
| 11303 } else { | 11315 } else { |
| 11304 return Integer::New(value); | 11316 return Integer::New(value); |
| 11305 } | 11317 } |
| 11306 } | 11318 } |
| 11307 | 11319 |
| 11308 | 11320 |
| 11309 double Integer::AsDoubleValue() const { | 11321 double Integer::AsDoubleValue() const { |
| 11310 UNIMPLEMENTED(); | 11322 UNIMPLEMENTED(); |
| 11311 return 0.0; | 11323 return 0.0; |
| 11312 } | 11324 } |
| 11313 | 11325 |
| 11314 | 11326 |
| 11315 int64_t Integer::AsInt64Value() const { | 11327 int64_t Integer::AsInt64Value() const { |
| 11316 UNIMPLEMENTED(); | 11328 UNIMPLEMENTED(); |
| 11317 return 0; | 11329 return 0; |
| 11318 } | 11330 } |
| 11319 | 11331 |
| 11320 | 11332 |
| 11321 int Integer::CompareWith(const Integer& other) const { | 11333 int Integer::CompareWith(const Integer& other) const { |
| 11322 UNIMPLEMENTED(); | 11334 UNIMPLEMENTED(); |
| 11323 return 0; | 11335 return 0; |
| 11324 } | 11336 } |
| 11325 | 11337 |
| 11326 | 11338 |
| 11327 // Returns true if the signed Integer requires more than 53 bits. | 11339 // Returns true if the signed Integer does not fit into a |
| 11328 bool Integer::CheckFiftyThreeBitOverflow() const { | 11340 // Javascript (54-bit) integer. |
| 11341 bool Integer::CheckJavascriptIntegerOverflow() const { | |
| 11329 // Always overflow if the value doesn't fit into an int64_t. | 11342 // Always overflow if the value doesn't fit into an int64_t. |
| 11330 int64_t value = 1ULL << 63; | 11343 int64_t value = 1ULL << 63; |
| 11331 if (IsSmi()) { | 11344 if (IsSmi()) { |
| 11332 value = AsInt64Value(); | 11345 value = AsInt64Value(); |
| 11333 } else if (IsMint()) { | 11346 } else if (IsMint()) { |
| 11334 Mint& mint = Mint::Handle(); | 11347 Mint& mint = Mint::Handle(); |
| 11335 mint ^= raw(); | 11348 mint ^= raw(); |
| 11336 value = mint.value(); | 11349 value = mint.value(); |
| 11337 } else { | 11350 } else { |
| 11338 ASSERT(IsBigint()); | 11351 ASSERT(IsBigint()); |
| 11339 Bigint& big_value = Bigint::Handle(); | 11352 Bigint& big_value = Bigint::Handle(); |
| 11340 big_value ^= raw(); | 11353 big_value ^= raw(); |
| 11341 if (BigintOperations::FitsIntoInt64(big_value)) { | 11354 if (BigintOperations::FitsIntoInt64(big_value)) { |
| 11342 value = BigintOperations::ToInt64(big_value); | 11355 value = BigintOperations::ToInt64(big_value); |
| 11343 } | 11356 } |
| 11344 } | 11357 } |
| 11345 return !Utils::IsInt(53, value); | 11358 return !Is54BitNoMinInt(value); |
| 11346 } | 11359 } |
| 11347 | 11360 |
| 11348 | 11361 |
| 11349 RawInteger* Integer::AsValidInteger() const { | 11362 RawInteger* Integer::AsValidInteger() const { |
| 11350 if (FLAG_throw_on_javascript_int_overflow && | 11363 if (FLAG_throw_on_javascript_int_overflow && |
| 11351 CheckFiftyThreeBitOverflow()) { | 11364 CheckJavascriptIntegerOverflow()) { |
| 11352 ThrowFiftyThreeBitOverflow(*this); | 11365 ThrowJavascriptIntegerOverflow(*this); |
| 11353 } | 11366 } |
| 11354 if (IsSmi()) return raw(); | 11367 if (IsSmi()) return raw(); |
| 11355 if (IsMint()) { | 11368 if (IsMint()) { |
| 11356 Mint& mint = Mint::Handle(); | 11369 Mint& mint = Mint::Handle(); |
| 11357 mint ^= raw(); | 11370 mint ^= raw(); |
| 11358 if (Smi::IsValid64(mint.value())) { | 11371 if (Smi::IsValid64(mint.value())) { |
| 11359 return Smi::New(mint.value()); | 11372 return Smi::New(mint.value()); |
| 11360 } else { | 11373 } else { |
| 11361 return raw(); | 11374 return raw(); |
| 11362 } | 11375 } |
| (...skipping 3019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14382 } | 14395 } |
| 14383 | 14396 |
| 14384 | 14397 |
| 14385 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 14398 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
| 14386 stream->OpenObject(); | 14399 stream->OpenObject(); |
| 14387 stream->CloseObject(); | 14400 stream->CloseObject(); |
| 14388 } | 14401 } |
| 14389 | 14402 |
| 14390 | 14403 |
| 14391 } // namespace dart | 14404 } // namespace dart |
| OLD | NEW |