Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | |
| 7 #include <iomanip> | 8 #include <iomanip> |
| 8 #include <sstream> | 9 #include <sstream> |
| 9 | 10 |
| 10 #include "src/accessors.h" | 11 #include "src/accessors.h" |
| 11 #include "src/allocation-site-scopes.h" | 12 #include "src/allocation-site-scopes.h" |
| 12 #include "src/api.h" | 13 #include "src/api.h" |
| 13 #include "src/arguments.h" | 14 #include "src/arguments.h" |
| 14 #include "src/base/bits.h" | 15 #include "src/base/bits.h" |
| 15 #include "src/base/utils/random-number-generator.h" | 16 #include "src/base/utils/random-number-generator.h" |
| 16 #include "src/bootstrapper.h" | 17 #include "src/bootstrapper.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 if (IsString()) return String::cast(this)->length() != 0; | 157 if (IsString()) return String::cast(this)->length() != 0; |
| 157 if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); | 158 if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); |
| 158 return true; | 159 return true; |
| 159 } | 160 } |
| 160 | 161 |
| 161 | 162 |
| 162 namespace { | 163 namespace { |
| 163 | 164 |
| 164 // TODO(bmeurer): Maybe we should introduce a marker interface Number, | 165 // TODO(bmeurer): Maybe we should introduce a marker interface Number, |
| 165 // where we put all these methods at some point? | 166 // where we put all these methods at some point? |
| 167 ComparisonResult NumberCompare(double x, double y) { | |
| 168 if (std::isnan(x) || std::isnan(y)) { | |
| 169 return ComparisonResult::kUndefined; | |
| 170 } else if (x < y) { | |
| 171 return ComparisonResult::kLessThan; | |
| 172 } else if (x > y) { | |
| 173 return ComparisonResult::kGreaterThan; | |
| 174 } else { | |
| 175 return ComparisonResult::kEqual; | |
| 176 } | |
| 177 } | |
| 178 | |
| 179 | |
| 166 bool NumberEquals(double x, double y) { | 180 bool NumberEquals(double x, double y) { |
| 167 // Must check explicitly for NaN's on Windows, but -0 works fine. | 181 // Must check explicitly for NaN's on Windows, but -0 works fine. |
| 168 if (std::isnan(x)) return false; | 182 if (std::isnan(x)) return false; |
| 169 if (std::isnan(y)) return false; | 183 if (std::isnan(y)) return false; |
| 170 return x == y; | 184 return x == y; |
| 171 } | 185 } |
| 172 | 186 |
| 173 | 187 |
| 174 bool NumberEquals(const Object* x, const Object* y) { | 188 bool NumberEquals(const Object* x, const Object* y) { |
| 175 return NumberEquals(x->Number(), y->Number()); | 189 return NumberEquals(x->Number(), y->Number()); |
| 176 } | 190 } |
| 177 | 191 |
| 178 | 192 |
| 179 bool NumberEquals(Handle<Object> x, Handle<Object> y) { | 193 bool NumberEquals(Handle<Object> x, Handle<Object> y) { |
| 180 return NumberEquals(*x, *y); | 194 return NumberEquals(*x, *y); |
| 181 } | 195 } |
| 182 | 196 |
| 183 } // namespace | 197 } // namespace |
| 184 | 198 |
| 185 | 199 |
| 186 // static | 200 // static |
| 201 Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y, | |
| 202 Strength strength) { | |
|
conradw
2015/09/18 08:59:22
We've been trying to use the Strength enum only fo
Benedikt Meurer
2015/09/18 09:52:03
Hm, that was totally non obvious from the comment
| |
| 203 if (!is_strong(strength)) { | |
| 204 // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4. | |
| 205 if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) || | |
| 206 !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) { | |
| 207 return Nothing<ComparisonResult>(); | |
| 208 } | |
| 209 } | |
| 210 if (x->IsString() && y->IsString()) { | |
| 211 // ES6 section 7.2.11 Abstract Relational Comparison step 5. | |
| 212 return Just( | |
| 213 String::Compare(Handle<String>::cast(x), Handle<String>::cast(y))); | |
| 214 } | |
| 215 // ES6 section 7.2.11 Abstract Relational Comparison step 6. | |
| 216 if (!is_strong(strength)) { | |
| 217 if (!Object::ToNumber(x).ToHandle(&x) || | |
| 218 !Object::ToNumber(y).ToHandle(&y)) { | |
| 219 return Nothing<ComparisonResult>(); | |
| 220 } | |
| 221 } else { | |
| 222 if (!x->IsNumber()) { | |
| 223 Isolate* const isolate = Handle<HeapObject>::cast(x)->GetIsolate(); | |
|
conradw
2015/09/18 08:59:22
Can the isolates ever be different here?
Benedikt Meurer
2015/09/18 09:52:03
No, but either x or y can be a Smi and therefore t
| |
| 224 isolate->Throw(*isolate->factory()->NewTypeError( | |
| 225 MessageTemplate::kStrongImplicitConversion)); | |
| 226 return Nothing<ComparisonResult>(); | |
| 227 } else if (!y->IsNumber()) { | |
| 228 Isolate* const isolate = Handle<HeapObject>::cast(y)->GetIsolate(); | |
| 229 isolate->Throw(*isolate->factory()->NewTypeError( | |
| 230 MessageTemplate::kStrongImplicitConversion)); | |
| 231 return Nothing<ComparisonResult>(); | |
| 232 } | |
| 233 } | |
| 234 return Just(NumberCompare(x->Number(), y->Number())); | |
| 235 } | |
| 236 | |
| 237 | |
| 238 // static | |
| 187 Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) { | 239 Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) { |
| 188 while (true) { | 240 while (true) { |
| 189 if (x->IsNumber()) { | 241 if (x->IsNumber()) { |
| 190 if (y->IsNumber()) { | 242 if (y->IsNumber()) { |
| 191 return Just(NumberEquals(x, y)); | 243 return Just(NumberEquals(x, y)); |
| 192 } else if (y->IsBoolean()) { | 244 } else if (y->IsBoolean()) { |
| 193 return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number())); | 245 return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number())); |
| 194 } else if (y->IsString()) { | 246 } else if (y->IsString()) { |
| 195 return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y)))); | 247 return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y)))); |
| 196 } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) { | 248 } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) { |
| (...skipping 9399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9596 one_length); | 9648 one_length); |
| 9597 } else { | 9649 } else { |
| 9598 for (int i = 0; i < one_length; i++) { | 9650 for (int i = 0; i < one_length; i++) { |
| 9599 if (flat1.Get(i) != flat2.Get(i)) return false; | 9651 if (flat1.Get(i) != flat2.Get(i)) return false; |
| 9600 } | 9652 } |
| 9601 return true; | 9653 return true; |
| 9602 } | 9654 } |
| 9603 } | 9655 } |
| 9604 | 9656 |
| 9605 | 9657 |
| 9658 // static | |
| 9659 ComparisonResult String::Compare(Handle<String> x, Handle<String> y) { | |
| 9660 // A few fast case tests before we flatten. | |
| 9661 if (x.is_identical_to(y)) { | |
| 9662 return ComparisonResult::kEqual; | |
| 9663 } else if (y->length() == 0) { | |
| 9664 return x->length() == 0 ? ComparisonResult::kEqual | |
| 9665 : ComparisonResult::kGreaterThan; | |
| 9666 } else if (x->length() == 0) { | |
| 9667 return ComparisonResult::kLessThan; | |
| 9668 } | |
| 9669 | |
| 9670 int const d = x->Get(0) - y->Get(0); | |
| 9671 if (d < 0) { | |
| 9672 return ComparisonResult::kLessThan; | |
| 9673 } else if (d > 0) { | |
| 9674 return ComparisonResult::kGreaterThan; | |
| 9675 } | |
| 9676 | |
| 9677 // Slow case. | |
| 9678 x = String::Flatten(x); | |
| 9679 y = String::Flatten(y); | |
| 9680 | |
| 9681 DisallowHeapAllocation no_gc; | |
| 9682 ComparisonResult result = ComparisonResult::kEqual; | |
| 9683 int prefix_length = x->length(); | |
| 9684 if (y->length() < prefix_length) { | |
| 9685 prefix_length = y->length(); | |
| 9686 result = ComparisonResult::kGreaterThan; | |
| 9687 } else if (y->length() > prefix_length) { | |
| 9688 result = ComparisonResult::kLessThan; | |
| 9689 } | |
| 9690 int r; | |
| 9691 String::FlatContent x_content = x->GetFlatContent(); | |
| 9692 String::FlatContent y_content = y->GetFlatContent(); | |
| 9693 if (x_content.IsOneByte()) { | |
| 9694 Vector<const uint8_t> x_chars = x_content.ToOneByteVector(); | |
| 9695 if (y_content.IsOneByte()) { | |
| 9696 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); | |
| 9697 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | |
| 9698 } else { | |
| 9699 Vector<const uc16> y_chars = y_content.ToUC16Vector(); | |
| 9700 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | |
| 9701 } | |
| 9702 } else { | |
| 9703 Vector<const uc16> x_chars = x_content.ToUC16Vector(); | |
| 9704 if (y_content.IsOneByte()) { | |
| 9705 Vector<const uint8_t> y_chars = y_content.ToOneByteVector(); | |
| 9706 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | |
| 9707 } else { | |
| 9708 Vector<const uc16> y_chars = y_content.ToUC16Vector(); | |
| 9709 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | |
| 9710 } | |
| 9711 } | |
| 9712 if (r < 0) { | |
| 9713 result = ComparisonResult::kLessThan; | |
| 9714 } else if (r > 0) { | |
| 9715 result = ComparisonResult::kGreaterThan; | |
| 9716 } | |
| 9717 return result; | |
| 9718 } | |
| 9719 | |
| 9720 | |
| 9606 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) { | 9721 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) { |
| 9607 int slen = length(); | 9722 int slen = length(); |
| 9608 // Can't check exact length equality, but we can check bounds. | 9723 // Can't check exact length equality, but we can check bounds. |
| 9609 int str_len = str.length(); | 9724 int str_len = str.length(); |
| 9610 if (!allow_prefix_match && | 9725 if (!allow_prefix_match && |
| 9611 (str_len < slen || | 9726 (str_len < slen || |
| 9612 str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) { | 9727 str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) { |
| 9613 return false; | 9728 return false; |
| 9614 } | 9729 } |
| 9615 int i; | 9730 int i; |
| (...skipping 6959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16575 if (cell->value() != *new_value) { | 16690 if (cell->value() != *new_value) { |
| 16576 cell->set_value(*new_value); | 16691 cell->set_value(*new_value); |
| 16577 Isolate* isolate = cell->GetIsolate(); | 16692 Isolate* isolate = cell->GetIsolate(); |
| 16578 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16693 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16579 isolate, DependentCode::kPropertyCellChangedGroup); | 16694 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16580 } | 16695 } |
| 16581 } | 16696 } |
| 16582 | 16697 |
| 16583 } // namespace internal | 16698 } // namespace internal |
| 16584 } // namespace v8 | 16699 } // namespace v8 |
| OLD | NEW |