Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: runtime/vm/object.cc

Issue 21301003: Fixes javascript integer overflow check. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 integer arithmetic exceeds 54 bits.");
56 DECLARE_FLAG(bool, trace_compiler); 56 DECLARE_FLAG(bool, trace_compiler);
57 DECLARE_FLAG(bool, eliminate_type_checks); 57 DECLARE_FLAG(bool, eliminate_type_checks);
58 DECLARE_FLAG(bool, enable_type_checks); 58 DECLARE_FLAG(bool, enable_type_checks);
59 59
60 static const char* kGetterPrefix = "get:"; 60 static const char* kGetterPrefix = "get:";
61 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); 61 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
62 static const char* kSetterPrefix = "set:"; 62 static const char* kSetterPrefix = "set:";
63 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); 63 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix);
64 64
65 cpp_vtable Object::handle_vtable_ = 0; 65 cpp_vtable Object::handle_vtable_ = 0;
(...skipping 11160 matching lines...) Expand 10 before | Expand all | Expand 10 after
11226 return "Integer"; 11226 return "Integer";
11227 } 11227 }
11228 11228
11229 11229
11230 void Integer::PrintToJSONStream(JSONStream* stream, bool ref) const { 11230 void Integer::PrintToJSONStream(JSONStream* stream, bool ref) const {
11231 stream->OpenObject(); 11231 stream->OpenObject();
11232 stream->CloseObject(); 11232 stream->CloseObject();
11233 } 11233 }
11234 11234
11235 11235
11236 // Throw FiftyThreeBitOverflow exception. 11236 // Throw FiftyFourBitOverflow exception.
11237 static void ThrowFiftyThreeBitOverflow(const Integer& i) { 11237 static void ThrowFiftyFourBitOverflow(const Integer& i) {
11238 const Array& exc_args = Array::Handle(Array::New(1)); 11238 const Array& exc_args = Array::Handle(Array::New(1));
11239 const String& i_str = String::Handle(String::New(i.ToCString())); 11239 const String& i_str = String::Handle(String::New(i.ToCString()));
11240 exc_args.SetAt(0, i_str); 11240 exc_args.SetAt(0, i_str);
11241 Exceptions::ThrowByType(Exceptions::kFiftyThreeBitOverflowError, exc_args); 11241 Exceptions::ThrowByType(Exceptions::kFiftyFourBitOverflowError, exc_args);
11242 } 11242 }
11243 11243
11244 11244
11245 RawInteger* Integer::New(const String& str, Heap::Space space) { 11245 RawInteger* Integer::New(const String& str, Heap::Space space) {
11246 // We are not supposed to have integers represented as two byte strings. 11246 // We are not supposed to have integers represented as two byte strings.
11247 ASSERT(str.IsOneByteString()); 11247 ASSERT(str.IsOneByteString());
11248 int64_t value; 11248 int64_t value;
11249 if (!OS::StringToInt64(str.ToCString(), &value)) { 11249 if (!OS::StringToInt64(str.ToCString(), &value)) {
11250 const Bigint& big = Bigint::Handle(Bigint::New(str, space)); 11250 const Bigint& big = Bigint::Handle(Bigint::New(str, space));
11251 ASSERT(!BigintOperations::FitsIntoSmi(big)); 11251 ASSERT(!BigintOperations::FitsIntoSmi(big));
11252 ASSERT(!BigintOperations::FitsIntoInt64(big)); 11252 ASSERT(!BigintOperations::FitsIntoInt64(big));
11253 if (FLAG_throw_on_javascript_int_overflow) { 11253 if (FLAG_throw_on_javascript_int_overflow) {
11254 ThrowFiftyThreeBitOverflow(big); 11254 ThrowFiftyFourBitOverflow(big);
11255 } 11255 }
11256 return big.raw(); 11256 return big.raw();
11257 } 11257 }
11258 return Integer::New(value, space); 11258 return Integer::New(value, space);
11259 } 11259 }
11260 11260
11261 11261
11262 // This is called from LiteralToken::New() in the parser, so we can't 11262 // 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 11263 // raise an exception for 54-bit overflow here. Instead we do it in
11264 // Parser::CurrentIntegerLiteral(), which is the point in the parser where 11264 // Parser::CurrentIntegerLiteral(), which is the point in the parser where
11265 // integer literals escape, so we can call Parser::ErrorMsg(). 11265 // integer literals escape, so we can call Parser::ErrorMsg().
11266 RawInteger* Integer::NewCanonical(const String& str) { 11266 RawInteger* Integer::NewCanonical(const String& str) {
11267 // We are not supposed to have integers represented as two byte strings. 11267 // We are not supposed to have integers represented as two byte strings.
11268 ASSERT(str.IsOneByteString()); 11268 ASSERT(str.IsOneByteString());
11269 int64_t value; 11269 int64_t value;
11270 if (!OS::StringToInt64(str.ToCString(), &value)) { 11270 if (!OS::StringToInt64(str.ToCString(), &value)) {
11271 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); 11271 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str));
11272 ASSERT(!BigintOperations::FitsIntoSmi(big)); 11272 ASSERT(!BigintOperations::FitsIntoSmi(big));
11273 ASSERT(!BigintOperations::FitsIntoInt64(big)); 11273 ASSERT(!BigintOperations::FitsIntoInt64(big));
11274 return big.raw(); 11274 return big.raw();
11275 } 11275 }
11276 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) { 11276 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) {
11277 return Smi::New(value); 11277 return Smi::New(value);
11278 } 11278 }
11279 return Mint::NewCanonical(value); 11279 return Mint::NewCanonical(value);
11280 } 11280 }
11281 11281
11282 11282
11283 // Floating point has a sign bit and 53 bits of fraction. When the sign bit is
11284 // set, and the fraction is 0, the result is -0.0, not MIN_53BIT_INT.
siva 2013/07/31 16:08:28 The comment here is a bit confusing as we are deal
zra 2013/07/31 17:46:31 Done.
11285 static bool Is54BitNoMinInt(int64_t value) {
11286 return (Utils::IsInt(54, value)) && (value != (-0x1FFFFFFFFFFFFF - 1));
11287 }
11288
11289
11283 RawInteger* Integer::New(int64_t value, Heap::Space space) { 11290 RawInteger* Integer::New(int64_t value, Heap::Space space) {
11284 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) { 11291 if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) {
11285 return Smi::New(value); 11292 return Smi::New(value);
11286 } 11293 }
11287 if (FLAG_throw_on_javascript_int_overflow && !Utils::IsInt(53, value)) { 11294 if (FLAG_throw_on_javascript_int_overflow && !Is54BitNoMinInt(value)) {
11288 const Integer &i = Integer::Handle(Mint::New(value)); 11295 const Integer &i = Integer::Handle(Mint::New(value));
11289 ThrowFiftyThreeBitOverflow(i); 11296 ThrowFiftyFourBitOverflow(i);
11290 } 11297 }
11291 return Mint::New(value, space); 11298 return Mint::New(value, space);
11292 } 11299 }
11293 11300
11294 11301
11295 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { 11302 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) {
11296 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { 11303 if (value > static_cast<uint64_t>(Mint::kMaxValue)) {
11297 if (FLAG_throw_on_javascript_int_overflow) { 11304 if (FLAG_throw_on_javascript_int_overflow) {
11298 const Integer &i = 11305 const Integer &i =
11299 Integer::Handle(BigintOperations::NewFromUint64(value)); 11306 Integer::Handle(BigintOperations::NewFromUint64(value));
11300 ThrowFiftyThreeBitOverflow(i); 11307 ThrowFiftyFourBitOverflow(i);
11301 } 11308 }
11302 return BigintOperations::NewFromUint64(value); 11309 return BigintOperations::NewFromUint64(value);
11303 } else { 11310 } else {
11304 return Integer::New(value); 11311 return Integer::New(value);
11305 } 11312 }
11306 } 11313 }
11307 11314
11308 11315
11309 double Integer::AsDoubleValue() const { 11316 double Integer::AsDoubleValue() const {
11310 UNIMPLEMENTED(); 11317 UNIMPLEMENTED();
11311 return 0.0; 11318 return 0.0;
11312 } 11319 }
11313 11320
11314 11321
11315 int64_t Integer::AsInt64Value() const { 11322 int64_t Integer::AsInt64Value() const {
11316 UNIMPLEMENTED(); 11323 UNIMPLEMENTED();
11317 return 0; 11324 return 0;
11318 } 11325 }
11319 11326
11320 11327
11321 int Integer::CompareWith(const Integer& other) const { 11328 int Integer::CompareWith(const Integer& other) const {
11322 UNIMPLEMENTED(); 11329 UNIMPLEMENTED();
11323 return 0; 11330 return 0;
11324 } 11331 }
11325 11332
11326 11333
11327 // Returns true if the signed Integer requires more than 53 bits. 11334 // Returns true if the signed Integer requires more than 54 bits.
11328 bool Integer::CheckFiftyThreeBitOverflow() const { 11335 bool Integer::CheckFiftyFourBitOverflow() const {
11329 // Always overflow if the value doesn't fit into an int64_t. 11336 // Always overflow if the value doesn't fit into an int64_t.
11330 int64_t value = 1ULL << 63; 11337 int64_t value = 1ULL << 63;
11331 if (IsSmi()) { 11338 if (IsSmi()) {
11332 value = AsInt64Value(); 11339 value = AsInt64Value();
11333 } else if (IsMint()) { 11340 } else if (IsMint()) {
11334 Mint& mint = Mint::Handle(); 11341 Mint& mint = Mint::Handle();
11335 mint ^= raw(); 11342 mint ^= raw();
11336 value = mint.value(); 11343 value = mint.value();
11337 } else { 11344 } else {
11338 ASSERT(IsBigint()); 11345 ASSERT(IsBigint());
11339 Bigint& big_value = Bigint::Handle(); 11346 Bigint& big_value = Bigint::Handle();
11340 big_value ^= raw(); 11347 big_value ^= raw();
11341 if (BigintOperations::FitsIntoInt64(big_value)) { 11348 if (BigintOperations::FitsIntoInt64(big_value)) {
11342 value = BigintOperations::ToInt64(big_value); 11349 value = BigintOperations::ToInt64(big_value);
11343 } 11350 }
11344 } 11351 }
11345 return !Utils::IsInt(53, value); 11352 return !Is54BitNoMinInt(value);
11346 } 11353 }
11347 11354
11348 11355
11349 RawInteger* Integer::AsValidInteger() const { 11356 RawInteger* Integer::AsValidInteger() const {
11350 if (FLAG_throw_on_javascript_int_overflow && 11357 if (FLAG_throw_on_javascript_int_overflow &&
11351 CheckFiftyThreeBitOverflow()) { 11358 CheckFiftyFourBitOverflow()) {
11352 ThrowFiftyThreeBitOverflow(*this); 11359 ThrowFiftyFourBitOverflow(*this);
11353 } 11360 }
11354 if (IsSmi()) return raw(); 11361 if (IsSmi()) return raw();
11355 if (IsMint()) { 11362 if (IsMint()) {
11356 Mint& mint = Mint::Handle(); 11363 Mint& mint = Mint::Handle();
11357 mint ^= raw(); 11364 mint ^= raw();
11358 if (Smi::IsValid64(mint.value())) { 11365 if (Smi::IsValid64(mint.value())) {
11359 return Smi::New(mint.value()); 11366 return Smi::New(mint.value());
11360 } else { 11367 } else {
11361 return raw(); 11368 return raw();
11362 } 11369 }
(...skipping 3019 matching lines...) Expand 10 before | Expand all | Expand 10 after
14382 } 14389 }
14383 14390
14384 14391
14385 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 14392 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
14386 stream->OpenObject(); 14393 stream->OpenObject();
14387 stream->CloseObject(); 14394 stream->CloseObject();
14388 } 14395 }
14389 14396
14390 14397
14391 } // namespace dart 14398 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698