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 |