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 <iomanip> | 7 #include <iomanip> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 return result; | 91 return result; |
92 } | 92 } |
93 | 93 |
94 | 94 |
95 // static | 95 // static |
96 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { | 96 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { |
97 while (true) { | 97 while (true) { |
98 if (input->IsNumber()) { | 98 if (input->IsNumber()) { |
99 return input; | 99 return input; |
100 } | 100 } |
101 Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate(); | |
102 if (input->IsOddball()) { | |
103 return handle(Handle<Oddball>::cast(input)->to_number(), isolate); | |
104 } | |
105 if (input->IsString()) { | 101 if (input->IsString()) { |
106 return String::ToNumber(Handle<String>::cast(input)); | 102 return String::ToNumber(Handle<String>::cast(input)); |
107 } | 103 } |
| 104 if (input->IsOddball()) { |
| 105 return Oddball::ToNumber(Handle<Oddball>::cast(input)); |
| 106 } |
| 107 Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate(); |
108 if (input->IsSymbol()) { | 108 if (input->IsSymbol()) { |
109 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber), | 109 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber), |
110 Object); | 110 Object); |
111 } | 111 } |
112 if (input->IsSimd128Value()) { | 112 if (input->IsSimd128Value()) { |
113 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber), | 113 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber), |
114 Object); | 114 Object); |
115 } | 115 } |
116 ASSIGN_RETURN_ON_EXCEPTION( | 116 ASSIGN_RETURN_ON_EXCEPTION( |
117 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), | 117 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 if (IsBoolean()) return IsTrue(); | 152 if (IsBoolean()) return IsTrue(); |
153 if (IsSmi()) return Smi::cast(this)->value() != 0; | 153 if (IsSmi()) return Smi::cast(this)->value() != 0; |
154 if (IsUndefined() || IsNull()) return false; | 154 if (IsUndefined() || IsNull()) return false; |
155 if (IsUndetectableObject()) return false; // Undetectable object is false. | 155 if (IsUndetectableObject()) return false; // Undetectable object is false. |
156 if (IsString()) return String::cast(this)->length() != 0; | 156 if (IsString()) return String::cast(this)->length() != 0; |
157 if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); | 157 if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue(); |
158 return true; | 158 return true; |
159 } | 159 } |
160 | 160 |
161 | 161 |
| 162 namespace { |
| 163 |
| 164 // TODO(bmeurer): Maybe we should introduce a marker interface Number, |
| 165 // where we put all these methods at some point? |
| 166 bool NumberEquals(double x, double y) { |
| 167 // Must check explicitly for NaN's on Windows, but -0 works fine. |
| 168 if (std::isnan(x)) return false; |
| 169 if (std::isnan(y)) return false; |
| 170 return x == y; |
| 171 } |
| 172 |
| 173 |
| 174 bool NumberEquals(const Object* x, const Object* y) { |
| 175 return NumberEquals(x->Number(), y->Number()); |
| 176 } |
| 177 |
| 178 |
| 179 bool NumberEquals(Handle<Object> x, Handle<Object> y) { |
| 180 return NumberEquals(*x, *y); |
| 181 } |
| 182 |
| 183 } // namespace |
| 184 |
| 185 |
| 186 // static |
| 187 Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) { |
| 188 while (true) { |
| 189 if (x->IsNumber()) { |
| 190 if (y->IsNumber()) { |
| 191 return Just(NumberEquals(x, y)); |
| 192 } else if (y->IsBoolean()) { |
| 193 return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number())); |
| 194 } else if (y->IsString()) { |
| 195 return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y)))); |
| 196 } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) { |
| 197 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y)) |
| 198 .ToHandle(&y)) { |
| 199 return Nothing<bool>(); |
| 200 } |
| 201 } else { |
| 202 return Just(false); |
| 203 } |
| 204 } else if (x->IsString()) { |
| 205 if (y->IsString()) { |
| 206 return Just( |
| 207 String::Equals(Handle<String>::cast(x), Handle<String>::cast(y))); |
| 208 } else if (y->IsNumber()) { |
| 209 x = String::ToNumber(Handle<String>::cast(x)); |
| 210 return Just(NumberEquals(x, y)); |
| 211 } else if (y->IsBoolean()) { |
| 212 x = String::ToNumber(Handle<String>::cast(x)); |
| 213 return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number())); |
| 214 } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) { |
| 215 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y)) |
| 216 .ToHandle(&y)) { |
| 217 return Nothing<bool>(); |
| 218 } |
| 219 } else { |
| 220 return Just(false); |
| 221 } |
| 222 } else if (x->IsBoolean()) { |
| 223 if (y->IsOddball()) { |
| 224 return Just(x.is_identical_to(y)); |
| 225 } else if (y->IsNumber()) { |
| 226 return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y)); |
| 227 } else if (y->IsString()) { |
| 228 y = String::ToNumber(Handle<String>::cast(y)); |
| 229 return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y)); |
| 230 } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) { |
| 231 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y)) |
| 232 .ToHandle(&y)) { |
| 233 return Nothing<bool>(); |
| 234 } |
| 235 x = Oddball::ToNumber(Handle<Oddball>::cast(x)); |
| 236 } else { |
| 237 return Just(false); |
| 238 } |
| 239 } else if (x->IsSymbol()) { |
| 240 return Just(x.is_identical_to(y)); |
| 241 } else if (x->IsSimd128Value()) { |
| 242 if (!y->IsSimd128Value()) return Just(false); |
| 243 return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x), |
| 244 Handle<Simd128Value>::cast(y))); |
| 245 } else if (x->IsJSReceiver() && !x->IsUndetectableObject()) { |
| 246 if (y->IsJSReceiver()) { |
| 247 return Just(x.is_identical_to(y)); |
| 248 } else if (y->IsNull() || y->IsSimd128Value() || y->IsSymbol() || |
| 249 y->IsUndefined()) { |
| 250 return Just(false); |
| 251 } else if (y->IsBoolean()) { |
| 252 y = Oddball::ToNumber(Handle<Oddball>::cast(y)); |
| 253 } |
| 254 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x)).ToHandle(&x)) { |
| 255 return Nothing<bool>(); |
| 256 } |
| 257 } else { |
| 258 return Just( |
| 259 (x->IsNull() || x->IsUndefined() || x->IsUndetectableObject()) && |
| 260 (y->IsNull() || y->IsUndefined() || y->IsUndetectableObject())); |
| 261 } |
| 262 } |
| 263 } |
| 264 |
| 265 |
162 bool Object::StrictEquals(Object* that) { | 266 bool Object::StrictEquals(Object* that) { |
163 if (this->IsNumber()) { | 267 if (this->IsNumber()) { |
164 if (!that->IsNumber()) return false; | 268 if (!that->IsNumber()) return false; |
165 double const x = this->Number(); | 269 return NumberEquals(this, that); |
166 double const y = that->Number(); | |
167 // Must check explicitly for NaN:s on Windows, but -0 works fine. | |
168 return x == y && !std::isnan(x) && !std::isnan(y); | |
169 } else if (this->IsString()) { | 270 } else if (this->IsString()) { |
170 if (!that->IsString()) return false; | 271 if (!that->IsString()) return false; |
171 return String::cast(this)->Equals(String::cast(that)); | 272 return String::cast(this)->Equals(String::cast(that)); |
172 } else if (this->IsSimd128Value()) { | 273 } else if (this->IsSimd128Value()) { |
173 if (!that->IsSimd128Value()) return false; | 274 if (!that->IsSimd128Value()) return false; |
174 return Simd128Value::cast(this)->Equals(Simd128Value::cast(that)); | 275 return Simd128Value::cast(this)->Equals(Simd128Value::cast(that)); |
175 } | 276 } |
176 return this == that; | 277 return this == that; |
177 } | 278 } |
178 | 279 |
(...skipping 16184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16363 if (cell->value() != *new_value) { | 16464 if (cell->value() != *new_value) { |
16364 cell->set_value(*new_value); | 16465 cell->set_value(*new_value); |
16365 Isolate* isolate = cell->GetIsolate(); | 16466 Isolate* isolate = cell->GetIsolate(); |
16366 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16467 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16367 isolate, DependentCode::kPropertyCellChangedGroup); | 16468 isolate, DependentCode::kPropertyCellChangedGroup); |
16368 } | 16469 } |
16369 } | 16470 } |
16370 | 16471 |
16371 } // namespace internal | 16472 } // namespace internal |
16372 } // namespace v8 | 16473 } // namespace v8 |
OLD | NEW |