| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 | 139 |
| 140 | 140 |
| 141 static Failure* ThrowArrayLengthRangeError(Heap* heap) { | 141 static Failure* ThrowArrayLengthRangeError(Heap* heap) { |
| 142 HandleScope scope(heap->isolate()); | 142 HandleScope scope(heap->isolate()); |
| 143 return heap->isolate()->Throw( | 143 return heap->isolate()->Throw( |
| 144 *heap->isolate()->factory()->NewRangeError("invalid_array_length", | 144 *heap->isolate()->factory()->NewRangeError("invalid_array_length", |
| 145 HandleVector<Object>(NULL, 0))); | 145 HandleVector<Object>(NULL, 0))); |
| 146 } | 146 } |
| 147 | 147 |
| 148 | 148 |
| 149 static void CopyObjectToObjectElements(FixedArray* from, | 149 static void CopyObjectToObjectElements(FixedArrayBase* from_base, |
| 150 ElementsKind from_kind, | 150 ElementsKind from_kind, |
| 151 uint32_t from_start, | 151 uint32_t from_start, |
| 152 FixedArray* to, | 152 FixedArrayBase* to_base, |
| 153 ElementsKind to_kind, | 153 ElementsKind to_kind, |
| 154 uint32_t to_start, | 154 uint32_t to_start, |
| 155 int raw_copy_size) { | 155 int raw_copy_size) { |
| 156 ASSERT(to->map() != HEAP->fixed_cow_array_map()); | 156 ASSERT(to_base->map() != HEAP->fixed_cow_array_map()); |
| 157 AssertNoAllocation no_allocation; | 157 AssertNoAllocation no_allocation; |
| 158 int copy_size = raw_copy_size; | 158 int copy_size = raw_copy_size; |
| 159 if (raw_copy_size < 0) { | 159 if (raw_copy_size < 0) { |
| 160 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 160 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 161 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 161 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 162 copy_size = Min(from->length() - from_start, | 162 copy_size = Min(from_base->length() - from_start, |
| 163 to->length() - to_start); | 163 to_base->length() - to_start); |
| 164 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 164 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 165 int start = to_start + copy_size; | 165 int start = to_start + copy_size; |
| 166 int length = to->length() - start; | 166 int length = to_base->length() - start; |
| 167 if (length > 0) { | 167 if (length > 0) { |
| 168 Heap* heap = from->GetHeap(); | 168 Heap* heap = from_base->GetHeap(); |
| 169 MemsetPointer(to->data_start() + start, heap->the_hole_value(), length); | 169 MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
| 170 heap->the_hole_value(), length); |
| 170 } | 171 } |
| 171 } | 172 } |
| 172 } | 173 } |
| 173 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 174 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
| 174 (copy_size + static_cast<int>(from_start)) <= from->length()); | 175 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
| 175 if (copy_size == 0) return; | 176 if (copy_size == 0) return; |
| 177 FixedArray* from = FixedArray::cast(from_base); |
| 178 FixedArray* to = FixedArray::cast(to_base); |
| 176 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); | 179 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); |
| 177 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 180 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
| 178 Address to_address = to->address() + FixedArray::kHeaderSize; | 181 Address to_address = to->address() + FixedArray::kHeaderSize; |
| 179 Address from_address = from->address() + FixedArray::kHeaderSize; | 182 Address from_address = from->address() + FixedArray::kHeaderSize; |
| 180 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, | 183 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, |
| 181 reinterpret_cast<Object**>(from_address) + from_start, | 184 reinterpret_cast<Object**>(from_address) + from_start, |
| 182 copy_size); | 185 copy_size); |
| 183 if (IsFastObjectElementsKind(from_kind) && | 186 if (IsFastObjectElementsKind(from_kind) && |
| 184 IsFastObjectElementsKind(to_kind)) { | 187 IsFastObjectElementsKind(to_kind)) { |
| 185 Heap* heap = from->GetHeap(); | 188 Heap* heap = from->GetHeap(); |
| 186 if (!heap->InNewSpace(to)) { | 189 if (!heap->InNewSpace(to)) { |
| 187 heap->RecordWrites(to->address(), | 190 heap->RecordWrites(to->address(), |
| 188 to->OffsetOfElementAt(to_start), | 191 to->OffsetOfElementAt(to_start), |
| 189 copy_size); | 192 copy_size); |
| 190 } | 193 } |
| 191 heap->incremental_marking()->RecordWrites(to); | 194 heap->incremental_marking()->RecordWrites(to); |
| 192 } | 195 } |
| 193 } | 196 } |
| 194 | 197 |
| 195 | 198 |
| 196 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, | 199 static void CopyDictionaryToObjectElements(FixedArrayBase* from_base, |
| 197 uint32_t from_start, | 200 uint32_t from_start, |
| 198 FixedArray* to, | 201 FixedArrayBase* to_base, |
| 199 ElementsKind to_kind, | 202 ElementsKind to_kind, |
| 200 uint32_t to_start, | 203 uint32_t to_start, |
| 201 int raw_copy_size) { | 204 int raw_copy_size) { |
| 205 SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base); |
| 202 AssertNoAllocation no_allocation; | 206 AssertNoAllocation no_allocation; |
| 203 int copy_size = raw_copy_size; | 207 int copy_size = raw_copy_size; |
| 204 Heap* heap = from->GetHeap(); | 208 Heap* heap = from->GetHeap(); |
| 205 if (raw_copy_size < 0) { | 209 if (raw_copy_size < 0) { |
| 206 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 210 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 207 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 211 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 208 copy_size = from->max_number_key() + 1 - from_start; | 212 copy_size = from->max_number_key() + 1 - from_start; |
| 209 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 213 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 210 int start = to_start + copy_size; | 214 int start = to_start + copy_size; |
| 211 int length = to->length() - start; | 215 int length = to_base->length() - start; |
| 212 if (length > 0) { | 216 if (length > 0) { |
| 213 Heap* heap = from->GetHeap(); | 217 Heap* heap = from->GetHeap(); |
| 214 MemsetPointer(to->data_start() + start, heap->the_hole_value(), length); | 218 MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
| 219 heap->the_hole_value(), length); |
| 215 } | 220 } |
| 216 } | 221 } |
| 217 } | 222 } |
| 218 ASSERT(to != from); | 223 ASSERT(to_base != from_base); |
| 219 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 224 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
| 220 if (copy_size == 0) return; | 225 if (copy_size == 0) return; |
| 226 FixedArray* to = FixedArray::cast(to_base); |
| 221 uint32_t to_length = to->length(); | 227 uint32_t to_length = to->length(); |
| 222 if (to_start + copy_size > to_length) { | 228 if (to_start + copy_size > to_length) { |
| 223 copy_size = to_length - to_start; | 229 copy_size = to_length - to_start; |
| 224 } | 230 } |
| 225 for (int i = 0; i < copy_size; i++) { | 231 for (int i = 0; i < copy_size; i++) { |
| 226 int entry = from->FindEntry(i + from_start); | 232 int entry = from->FindEntry(i + from_start); |
| 227 if (entry != SeededNumberDictionary::kNotFound) { | 233 if (entry != SeededNumberDictionary::kNotFound) { |
| 228 Object* value = from->ValueAt(entry); | 234 Object* value = from->ValueAt(entry); |
| 229 ASSERT(!value->IsTheHole()); | 235 ASSERT(!value->IsTheHole()); |
| 230 to->set(i + to_start, value, SKIP_WRITE_BARRIER); | 236 to->set(i + to_start, value, SKIP_WRITE_BARRIER); |
| 231 } else { | 237 } else { |
| 232 to->set_the_hole(i + to_start); | 238 to->set_the_hole(i + to_start); |
| 233 } | 239 } |
| 234 } | 240 } |
| 235 if (IsFastObjectElementsKind(to_kind)) { | 241 if (IsFastObjectElementsKind(to_kind)) { |
| 236 if (!heap->InNewSpace(to)) { | 242 if (!heap->InNewSpace(to)) { |
| 237 heap->RecordWrites(to->address(), | 243 heap->RecordWrites(to->address(), |
| 238 to->OffsetOfElementAt(to_start), | 244 to->OffsetOfElementAt(to_start), |
| 239 copy_size); | 245 copy_size); |
| 240 } | 246 } |
| 241 heap->incremental_marking()->RecordWrites(to); | 247 heap->incremental_marking()->RecordWrites(to); |
| 242 } | 248 } |
| 243 } | 249 } |
| 244 | 250 |
| 245 | 251 |
| 246 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( | 252 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( |
| 247 FixedDoubleArray* from, | 253 FixedArrayBase* from_base, |
| 248 uint32_t from_start, | 254 uint32_t from_start, |
| 249 FixedArray* to, | 255 FixedArrayBase* to_base, |
| 250 ElementsKind to_kind, | 256 ElementsKind to_kind, |
| 251 uint32_t to_start, | 257 uint32_t to_start, |
| 252 int raw_copy_size) { | 258 int raw_copy_size) { |
| 253 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 259 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
| 254 int copy_size = raw_copy_size; | 260 int copy_size = raw_copy_size; |
| 255 if (raw_copy_size < 0) { | 261 if (raw_copy_size < 0) { |
| 256 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 262 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 257 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 263 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 258 copy_size = Min(from->length() - from_start, | 264 copy_size = Min(from_base->length() - from_start, |
| 259 to->length() - to_start); | 265 to_base->length() - to_start); |
| 260 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 266 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 261 // Also initialize the area that will be copied over since HeapNumber | 267 // Also initialize the area that will be copied over since HeapNumber |
| 262 // allocation below can cause an incremental marking step, requiring all | 268 // allocation below can cause an incremental marking step, requiring all |
| 263 // existing heap objects to be propertly initialized. | 269 // existing heap objects to be propertly initialized. |
| 264 int start = to_start; | 270 int start = to_start; |
| 265 int length = to->length() - start; | 271 int length = to_base->length() - start; |
| 266 if (length > 0) { | 272 if (length > 0) { |
| 267 Heap* heap = from->GetHeap(); | 273 Heap* heap = from_base->GetHeap(); |
| 268 MemsetPointer(to->data_start() + start, heap->the_hole_value(), length); | 274 MemsetPointer(FixedArray::cast(to_base)->data_start() + start, |
| 275 heap->the_hole_value(), length); |
| 269 } | 276 } |
| 270 } | 277 } |
| 271 } | 278 } |
| 272 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 279 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
| 273 (copy_size + static_cast<int>(from_start)) <= from->length()); | 280 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
| 274 if (copy_size == 0) return from; | 281 if (copy_size == 0) return from_base; |
| 282 FixedDoubleArray* from = FixedDoubleArray::cast(from_base); |
| 283 FixedArray* to = FixedArray::cast(to_base); |
| 275 for (int i = 0; i < copy_size; ++i) { | 284 for (int i = 0; i < copy_size; ++i) { |
| 276 if (IsFastSmiElementsKind(to_kind)) { | 285 if (IsFastSmiElementsKind(to_kind)) { |
| 277 UNIMPLEMENTED(); | 286 UNIMPLEMENTED(); |
| 278 return Failure::Exception(); | 287 return Failure::Exception(); |
| 279 } else { | 288 } else { |
| 280 MaybeObject* maybe_value = from->get(i + from_start); | 289 MaybeObject* maybe_value = from->get(i + from_start); |
| 281 Object* value; | 290 Object* value; |
| 282 ASSERT(IsFastObjectElementsKind(to_kind)); | 291 ASSERT(IsFastObjectElementsKind(to_kind)); |
| 283 // Because Double -> Object elements transitions allocate HeapObjects | 292 // Because Double -> Object elements transitions allocate HeapObjects |
| 284 // iteratively, the allocate must succeed within a single GC cycle, | 293 // iteratively, the allocate must succeed within a single GC cycle, |
| 285 // otherwise the retry after the GC will also fail. In order to ensure | 294 // otherwise the retry after the GC will also fail. In order to ensure |
| 286 // that no GC is triggered, allocate HeapNumbers from old space if they | 295 // that no GC is triggered, allocate HeapNumbers from old space if they |
| 287 // can't be taken from new space. | 296 // can't be taken from new space. |
| 288 if (!maybe_value->ToObject(&value)) { | 297 if (!maybe_value->ToObject(&value)) { |
| 289 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); | 298 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); |
| 290 Heap* heap = from->GetHeap(); | 299 Heap* heap = from->GetHeap(); |
| 291 MaybeObject* maybe_value_object = | 300 MaybeObject* maybe_value_object = |
| 292 heap->AllocateHeapNumber(from->get_scalar(i + from_start), | 301 heap->AllocateHeapNumber(from->get_scalar(i + from_start), |
| 293 TENURED); | 302 TENURED); |
| 294 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 303 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 295 } | 304 } |
| 296 to->set(i + to_start, value, UPDATE_WRITE_BARRIER); | 305 to->set(i + to_start, value, UPDATE_WRITE_BARRIER); |
| 297 } | 306 } |
| 298 } | 307 } |
| 299 return to; | 308 return to; |
| 300 } | 309 } |
| 301 | 310 |
| 302 | 311 |
| 303 static void CopyDoubleToDoubleElements(FixedDoubleArray* from, | 312 static void CopyDoubleToDoubleElements(FixedArrayBase* from_base, |
| 304 uint32_t from_start, | 313 uint32_t from_start, |
| 305 FixedDoubleArray* to, | 314 FixedArrayBase* to_base, |
| 306 uint32_t to_start, | 315 uint32_t to_start, |
| 307 int raw_copy_size) { | 316 int raw_copy_size) { |
| 308 int copy_size = raw_copy_size; | 317 int copy_size = raw_copy_size; |
| 309 if (raw_copy_size < 0) { | 318 if (raw_copy_size < 0) { |
| 310 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 319 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 311 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 320 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 312 copy_size = Min(from->length() - from_start, | 321 copy_size = Min(from_base->length() - from_start, |
| 313 to->length() - to_start); | 322 to_base->length() - to_start); |
| 314 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 323 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 315 for (int i = to_start + copy_size; i < to->length(); ++i) { | 324 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
| 316 to->set_the_hole(i); | 325 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
| 317 } | 326 } |
| 318 } | 327 } |
| 319 } | 328 } |
| 320 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 329 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
| 321 (copy_size + static_cast<int>(from_start)) <= from->length()); | 330 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
| 322 if (copy_size == 0) return; | 331 if (copy_size == 0) return; |
| 332 FixedDoubleArray* from = FixedDoubleArray::cast(from_base); |
| 333 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
| 323 Address to_address = to->address() + FixedDoubleArray::kHeaderSize; | 334 Address to_address = to->address() + FixedDoubleArray::kHeaderSize; |
| 324 Address from_address = from->address() + FixedDoubleArray::kHeaderSize; | 335 Address from_address = from->address() + FixedDoubleArray::kHeaderSize; |
| 325 to_address += kDoubleSize * to_start; | 336 to_address += kDoubleSize * to_start; |
| 326 from_address += kDoubleSize * from_start; | 337 from_address += kDoubleSize * from_start; |
| 327 int words_per_double = (kDoubleSize / kPointerSize); | 338 int words_per_double = (kDoubleSize / kPointerSize); |
| 328 CopyWords(reinterpret_cast<Object**>(to_address), | 339 CopyWords(reinterpret_cast<Object**>(to_address), |
| 329 reinterpret_cast<Object**>(from_address), | 340 reinterpret_cast<Object**>(from_address), |
| 330 words_per_double * copy_size); | 341 words_per_double * copy_size); |
| 331 } | 342 } |
| 332 | 343 |
| 333 | 344 |
| 334 static void CopySmiToDoubleElements(FixedArray* from, | 345 static void CopySmiToDoubleElements(FixedArrayBase* from_base, |
| 335 uint32_t from_start, | 346 uint32_t from_start, |
| 336 FixedDoubleArray* to, | 347 FixedArrayBase* to_base, |
| 337 uint32_t to_start, | 348 uint32_t to_start, |
| 338 int raw_copy_size) { | 349 int raw_copy_size) { |
| 339 int copy_size = raw_copy_size; | 350 int copy_size = raw_copy_size; |
| 340 if (raw_copy_size < 0) { | 351 if (raw_copy_size < 0) { |
| 341 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 352 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 342 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 353 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 343 copy_size = from->length() - from_start; | 354 copy_size = from_base->length() - from_start; |
| 344 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 355 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 345 for (int i = to_start + copy_size; i < to->length(); ++i) { | 356 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
| 346 to->set_the_hole(i); | 357 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
| 347 } | 358 } |
| 348 } | 359 } |
| 349 } | 360 } |
| 350 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 361 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
| 351 (copy_size + static_cast<int>(from_start)) <= from->length()); | 362 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
| 352 if (copy_size == 0) return; | 363 if (copy_size == 0) return; |
| 364 FixedArray* from = FixedArray::cast(from_base); |
| 365 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
| 353 Object* the_hole = from->GetHeap()->the_hole_value(); | 366 Object* the_hole = from->GetHeap()->the_hole_value(); |
| 354 for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size); | 367 for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size); |
| 355 from_start < from_end; from_start++, to_start++) { | 368 from_start < from_end; from_start++, to_start++) { |
| 356 Object* hole_or_smi = from->get(from_start); | 369 Object* hole_or_smi = from->get(from_start); |
| 357 if (hole_or_smi == the_hole) { | 370 if (hole_or_smi == the_hole) { |
| 358 to->set_the_hole(to_start); | 371 to->set_the_hole(to_start); |
| 359 } else { | 372 } else { |
| 360 to->set(to_start, Smi::cast(hole_or_smi)->value()); | 373 to->set(to_start, Smi::cast(hole_or_smi)->value()); |
| 361 } | 374 } |
| 362 } | 375 } |
| 363 } | 376 } |
| 364 | 377 |
| 365 | 378 |
| 366 static void CopyPackedSmiToDoubleElements(FixedArray* from, | 379 static void CopyPackedSmiToDoubleElements(FixedArrayBase* from_base, |
| 367 uint32_t from_start, | 380 uint32_t from_start, |
| 368 FixedDoubleArray* to, | 381 FixedArrayBase* to_base, |
| 369 uint32_t to_start, | 382 uint32_t to_start, |
| 370 int packed_size, | 383 int packed_size, |
| 371 int raw_copy_size) { | 384 int raw_copy_size) { |
| 372 int copy_size = raw_copy_size; | 385 int copy_size = raw_copy_size; |
| 373 uint32_t to_end; | 386 uint32_t to_end; |
| 374 if (raw_copy_size < 0) { | 387 if (raw_copy_size < 0) { |
| 375 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 388 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 376 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 389 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 377 copy_size = from->length() - from_start; | 390 copy_size = from_base->length() - from_start; |
| 378 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 391 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 379 to_end = to->length(); | 392 to_end = to_base->length(); |
| 380 for (uint32_t i = to_start + copy_size; i < to_end; ++i) { | 393 for (uint32_t i = to_start + copy_size; i < to_end; ++i) { |
| 381 to->set_the_hole(i); | 394 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
| 382 } | 395 } |
| 383 } else { | 396 } else { |
| 384 to_end = to_start + static_cast<uint32_t>(copy_size); | 397 to_end = to_start + static_cast<uint32_t>(copy_size); |
| 385 } | 398 } |
| 386 } else { | 399 } else { |
| 387 to_end = to_start + static_cast<uint32_t>(copy_size); | 400 to_end = to_start + static_cast<uint32_t>(copy_size); |
| 388 } | 401 } |
| 389 ASSERT(static_cast<int>(to_end) <= to->length()); | 402 ASSERT(static_cast<int>(to_end) <= to_base->length()); |
| 390 ASSERT(packed_size >= 0 && packed_size <= copy_size); | 403 ASSERT(packed_size >= 0 && packed_size <= copy_size); |
| 391 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 404 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
| 392 (copy_size + static_cast<int>(from_start)) <= from->length()); | 405 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
| 393 if (copy_size == 0) return; | 406 if (copy_size == 0) return; |
| 407 FixedArray* from = FixedArray::cast(from_base); |
| 408 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
| 394 for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size); | 409 for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size); |
| 395 from_start < from_end; from_start++, to_start++) { | 410 from_start < from_end; from_start++, to_start++) { |
| 396 Object* smi = from->get(from_start); | 411 Object* smi = from->get(from_start); |
| 397 ASSERT(!smi->IsTheHole()); | 412 ASSERT(!smi->IsTheHole()); |
| 398 to->set(to_start, Smi::cast(smi)->value()); | 413 to->set(to_start, Smi::cast(smi)->value()); |
| 399 } | 414 } |
| 400 } | 415 } |
| 401 | 416 |
| 402 | 417 |
| 403 static void CopyObjectToDoubleElements(FixedArray* from, | 418 static void CopyObjectToDoubleElements(FixedArrayBase* from_base, |
| 404 uint32_t from_start, | 419 uint32_t from_start, |
| 405 FixedDoubleArray* to, | 420 FixedArrayBase* to_base, |
| 406 uint32_t to_start, | 421 uint32_t to_start, |
| 407 int raw_copy_size) { | 422 int raw_copy_size) { |
| 408 int copy_size = raw_copy_size; | 423 int copy_size = raw_copy_size; |
| 409 if (raw_copy_size < 0) { | 424 if (raw_copy_size < 0) { |
| 410 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 425 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
| 411 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 426 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 412 copy_size = from->length() - from_start; | 427 copy_size = from_base->length() - from_start; |
| 413 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 428 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 414 for (int i = to_start + copy_size; i < to->length(); ++i) { | 429 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
| 415 to->set_the_hole(i); | 430 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
| 416 } | 431 } |
| 417 } | 432 } |
| 418 } | 433 } |
| 419 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 434 ASSERT((copy_size + static_cast<int>(to_start)) <= to_base->length() && |
| 420 (copy_size + static_cast<int>(from_start)) <= from->length()); | 435 (copy_size + static_cast<int>(from_start)) <= from_base->length()); |
| 421 if (copy_size == 0) return; | 436 if (copy_size == 0) return; |
| 437 FixedArray* from = FixedArray::cast(from_base); |
| 438 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
| 422 Object* the_hole = from->GetHeap()->the_hole_value(); | 439 Object* the_hole = from->GetHeap()->the_hole_value(); |
| 423 for (uint32_t from_end = from_start + copy_size; | 440 for (uint32_t from_end = from_start + copy_size; |
| 424 from_start < from_end; from_start++, to_start++) { | 441 from_start < from_end; from_start++, to_start++) { |
| 425 Object* hole_or_object = from->get(from_start); | 442 Object* hole_or_object = from->get(from_start); |
| 426 if (hole_or_object == the_hole) { | 443 if (hole_or_object == the_hole) { |
| 427 to->set_the_hole(to_start); | 444 to->set_the_hole(to_start); |
| 428 } else { | 445 } else { |
| 429 to->set(to_start, hole_or_object->Number()); | 446 to->set(to_start, hole_or_object->Number()); |
| 430 } | 447 } |
| 431 } | 448 } |
| 432 } | 449 } |
| 433 | 450 |
| 434 | 451 |
| 435 static void CopyDictionaryToDoubleElements(SeededNumberDictionary* from, | 452 static void CopyDictionaryToDoubleElements(FixedArrayBase* from_base, |
| 436 uint32_t from_start, | 453 uint32_t from_start, |
| 437 FixedDoubleArray* to, | 454 FixedArrayBase* to_base, |
| 438 uint32_t to_start, | 455 uint32_t to_start, |
| 439 int raw_copy_size) { | 456 int raw_copy_size) { |
| 457 SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base); |
| 440 int copy_size = raw_copy_size; | 458 int copy_size = raw_copy_size; |
| 441 if (copy_size < 0) { | 459 if (copy_size < 0) { |
| 442 ASSERT(copy_size == ElementsAccessor::kCopyToEnd || | 460 ASSERT(copy_size == ElementsAccessor::kCopyToEnd || |
| 443 copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 461 copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 444 copy_size = from->max_number_key() + 1 - from_start; | 462 copy_size = from->max_number_key() + 1 - from_start; |
| 445 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 463 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
| 446 for (int i = to_start + copy_size; i < to->length(); ++i) { | 464 for (int i = to_start + copy_size; i < to_base->length(); ++i) { |
| 447 to->set_the_hole(i); | 465 FixedDoubleArray::cast(to_base)->set_the_hole(i); |
| 448 } | 466 } |
| 449 } | 467 } |
| 450 } | 468 } |
| 451 if (copy_size == 0) return; | 469 if (copy_size == 0) return; |
| 470 FixedDoubleArray* to = FixedDoubleArray::cast(to_base); |
| 452 uint32_t to_length = to->length(); | 471 uint32_t to_length = to->length(); |
| 453 if (to_start + copy_size > to_length) { | 472 if (to_start + copy_size > to_length) { |
| 454 copy_size = to_length - to_start; | 473 copy_size = to_length - to_start; |
| 455 } | 474 } |
| 456 for (int i = 0; i < copy_size; i++) { | 475 for (int i = 0; i < copy_size; i++) { |
| 457 int entry = from->FindEntry(i + from_start); | 476 int entry = from->FindEntry(i + from_start); |
| 458 if (entry != SeededNumberDictionary::kNotFound) { | 477 if (entry != SeededNumberDictionary::kNotFound) { |
| 459 to->set(i + to_start, from->ValueAt(entry)->Number()); | 478 to->set(i + to_start, from->ValueAt(entry)->Number()); |
| 460 } else { | 479 } else { |
| 461 to->set_the_hole(i + to_start); | 480 to->set_the_hole(i + to_start); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 } | 553 } |
| 535 | 554 |
| 536 virtual bool HasElement(Object* receiver, | 555 virtual bool HasElement(Object* receiver, |
| 537 JSObject* holder, | 556 JSObject* holder, |
| 538 uint32_t key, | 557 uint32_t key, |
| 539 FixedArrayBase* backing_store) { | 558 FixedArrayBase* backing_store) { |
| 540 if (backing_store == NULL) { | 559 if (backing_store == NULL) { |
| 541 backing_store = holder->elements(); | 560 backing_store = holder->elements(); |
| 542 } | 561 } |
| 543 return ElementsAccessorSubclass::HasElementImpl( | 562 return ElementsAccessorSubclass::HasElementImpl( |
| 544 receiver, holder, key, BackingStore::cast(backing_store)); | 563 receiver, holder, key, backing_store); |
| 545 } | 564 } |
| 546 | 565 |
| 547 MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver, | 566 MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver, |
| 548 JSObject* holder, | 567 JSObject* holder, |
| 549 uint32_t key, | 568 uint32_t key, |
| 550 FixedArrayBase* backing_store) { | 569 FixedArrayBase* backing_store) { |
| 551 if (backing_store == NULL) { | 570 if (backing_store == NULL) { |
| 552 backing_store = holder->elements(); | 571 backing_store = holder->elements(); |
| 553 } | 572 } |
| 554 return ElementsAccessorSubclass::GetImpl( | 573 return ElementsAccessorSubclass::GetImpl( |
| 555 receiver, holder, key, BackingStore::cast(backing_store)); | 574 receiver, holder, key, backing_store); |
| 556 } | 575 } |
| 557 | 576 |
| 558 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, | 577 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, |
| 559 JSObject* obj, | 578 JSObject* obj, |
| 560 uint32_t key, | 579 uint32_t key, |
| 561 BackingStore* backing_store) { | 580 FixedArrayBase* backing_store) { |
| 562 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) | 581 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) |
| 563 ? backing_store->get(key) | 582 ? BackingStore::cast(backing_store)->get(key) |
| 564 : backing_store->GetHeap()->the_hole_value(); | 583 : backing_store->GetHeap()->the_hole_value(); |
| 565 } | 584 } |
| 566 | 585 |
| 567 MUST_USE_RESULT virtual PropertyAttributes GetAttributes( | 586 MUST_USE_RESULT virtual PropertyAttributes GetAttributes( |
| 568 Object* receiver, | 587 Object* receiver, |
| 569 JSObject* holder, | 588 JSObject* holder, |
| 570 uint32_t key, | 589 uint32_t key, |
| 571 FixedArrayBase* backing_store) { | 590 FixedArrayBase* backing_store) { |
| 572 if (backing_store == NULL) { | 591 if (backing_store == NULL) { |
| 573 backing_store = holder->elements(); | 592 backing_store = holder->elements(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 589 | 608 |
| 590 MUST_USE_RESULT virtual PropertyType GetType( | 609 MUST_USE_RESULT virtual PropertyType GetType( |
| 591 Object* receiver, | 610 Object* receiver, |
| 592 JSObject* holder, | 611 JSObject* holder, |
| 593 uint32_t key, | 612 uint32_t key, |
| 594 FixedArrayBase* backing_store) { | 613 FixedArrayBase* backing_store) { |
| 595 if (backing_store == NULL) { | 614 if (backing_store == NULL) { |
| 596 backing_store = holder->elements(); | 615 backing_store = holder->elements(); |
| 597 } | 616 } |
| 598 return ElementsAccessorSubclass::GetTypeImpl( | 617 return ElementsAccessorSubclass::GetTypeImpl( |
| 599 receiver, holder, key, BackingStore::cast(backing_store)); | 618 receiver, holder, key, backing_store); |
| 600 } | 619 } |
| 601 | 620 |
| 602 MUST_USE_RESULT static PropertyType GetTypeImpl( | 621 MUST_USE_RESULT static PropertyType GetTypeImpl( |
| 603 Object* receiver, | 622 Object* receiver, |
| 604 JSObject* obj, | 623 JSObject* obj, |
| 605 uint32_t key, | 624 uint32_t key, |
| 606 BackingStore* backing_store) { | 625 FixedArrayBase* backing_store) { |
| 607 if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) { | 626 if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) { |
| 608 return NONEXISTENT; | 627 return NONEXISTENT; |
| 609 } | 628 } |
| 610 return backing_store->is_the_hole(key) ? NONEXISTENT : FIELD; | 629 return BackingStore::cast(backing_store)->is_the_hole(key) |
| 630 ? NONEXISTENT : FIELD; |
| 611 } | 631 } |
| 612 | 632 |
| 613 MUST_USE_RESULT virtual AccessorPair* GetAccessorPair( | 633 MUST_USE_RESULT virtual AccessorPair* GetAccessorPair( |
| 614 Object* receiver, | 634 Object* receiver, |
| 615 JSObject* holder, | 635 JSObject* holder, |
| 616 uint32_t key, | 636 uint32_t key, |
| 617 FixedArrayBase* backing_store) { | 637 FixedArrayBase* backing_store) { |
| 618 if (backing_store == NULL) { | 638 if (backing_store == NULL) { |
| 619 backing_store = holder->elements(); | 639 backing_store = holder->elements(); |
| 620 } | 640 } |
| 621 return ElementsAccessorSubclass::GetAccessorPairImpl( | 641 return ElementsAccessorSubclass::GetAccessorPairImpl( |
| 622 receiver, holder, key, BackingStore::cast(backing_store)); | 642 receiver, holder, key, backing_store); |
| 623 } | 643 } |
| 624 | 644 |
| 625 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 645 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
| 626 Object* receiver, | 646 Object* receiver, |
| 627 JSObject* obj, | 647 JSObject* obj, |
| 628 uint32_t key, | 648 uint32_t key, |
| 629 BackingStore* backing_store) { | 649 FixedArrayBase* backing_store) { |
| 630 return NULL; | 650 return NULL; |
| 631 } | 651 } |
| 632 | 652 |
| 633 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array, | 653 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array, |
| 634 Object* length) { | 654 Object* length) { |
| 635 return ElementsAccessorSubclass::SetLengthImpl( | 655 return ElementsAccessorSubclass::SetLengthImpl( |
| 636 array, length, BackingStore::cast(array->elements())); | 656 array, length, array->elements()); |
| 637 } | 657 } |
| 638 | 658 |
| 639 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 659 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
| 640 JSObject* obj, | 660 JSObject* obj, |
| 641 Object* length, | 661 Object* length, |
| 642 BackingStore* backing_store); | 662 FixedArrayBase* backing_store); |
| 643 | 663 |
| 644 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( | 664 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( |
| 645 JSArray* array, | 665 JSArray* array, |
| 646 int capacity, | 666 int capacity, |
| 647 int length) { | 667 int length) { |
| 648 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 668 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
| 649 array, | 669 array, |
| 650 capacity, | 670 capacity, |
| 651 length); | 671 length); |
| 652 } | 672 } |
| 653 | 673 |
| 654 MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength( | 674 MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength( |
| 655 JSObject* obj, | 675 JSObject* obj, |
| 656 int capacity, | 676 int capacity, |
| 657 int length) { | 677 int length) { |
| 658 UNIMPLEMENTED(); | 678 UNIMPLEMENTED(); |
| 659 return obj; | 679 return obj; |
| 660 } | 680 } |
| 661 | 681 |
| 662 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 682 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
| 663 uint32_t key, | 683 uint32_t key, |
| 664 JSReceiver::DeleteMode mode) = 0; | 684 JSReceiver::DeleteMode mode) = 0; |
| 665 | 685 |
| 666 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 686 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 667 uint32_t from_start, | 687 uint32_t from_start, |
| 668 FixedArrayBase* to, | 688 FixedArrayBase* to, |
| 669 ElementsKind to_kind, | 689 ElementsKind from_kind, |
| 670 uint32_t to_start, | 690 uint32_t to_start, |
| 671 int packed_size, | 691 int packed_size, |
| 672 int copy_size) { | 692 int copy_size) { |
| 673 UNREACHABLE(); | 693 UNREACHABLE(); |
| 674 return NULL; | 694 return NULL; |
| 675 } | 695 } |
| 676 | 696 |
| 677 MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder, | 697 MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder, |
| 678 uint32_t from_start, | 698 uint32_t from_start, |
| 679 FixedArrayBase* to, | 699 FixedArrayBase* to, |
| 680 ElementsKind to_kind, | 700 ElementsKind from_kind, |
| 681 uint32_t to_start, | 701 uint32_t to_start, |
| 682 int copy_size, | 702 int copy_size, |
| 683 FixedArrayBase* from) { | 703 FixedArrayBase* from) { |
| 684 int packed_size = kPackedSizeNotKnown; | 704 int packed_size = kPackedSizeNotKnown; |
| 685 if (from == NULL) { | 705 if (from == NULL) { |
| 686 from = from_holder->elements(); | 706 from = from_holder->elements(); |
| 687 } | 707 } |
| 688 | 708 |
| 689 if (from_holder) { | 709 if (from_holder) { |
| 690 ElementsKind elements_kind = from_holder->GetElementsKind(); | 710 bool is_packed = IsFastPackedElementsKind(from_kind) && |
| 691 bool is_packed = IsFastPackedElementsKind(elements_kind) && | |
| 692 from_holder->IsJSArray(); | 711 from_holder->IsJSArray(); |
| 693 if (is_packed) { | 712 if (is_packed) { |
| 694 packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value(); | 713 packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value(); |
| 695 if (copy_size >= 0 && packed_size > copy_size) { | 714 if (copy_size >= 0 && packed_size > copy_size) { |
| 696 packed_size = copy_size; | 715 packed_size = copy_size; |
| 697 } | 716 } |
| 698 } | 717 } |
| 699 } | 718 } |
| 700 return ElementsAccessorSubclass::CopyElementsImpl( | 719 return ElementsAccessorSubclass::CopyElementsImpl( |
| 701 from, from_start, to, to_kind, to_start, packed_size, copy_size); | 720 from, from_start, to, from_kind, to_start, packed_size, copy_size); |
| 702 } | 721 } |
| 703 | 722 |
| 704 MUST_USE_RESULT virtual MaybeObject* AddElementsToFixedArray( | 723 MUST_USE_RESULT virtual MaybeObject* AddElementsToFixedArray( |
| 705 Object* receiver, | 724 Object* receiver, |
| 706 JSObject* holder, | 725 JSObject* holder, |
| 707 FixedArray* to, | 726 FixedArray* to, |
| 708 FixedArrayBase* from) { | 727 FixedArrayBase* from) { |
| 709 int len0 = to->length(); | 728 int len0 = to->length(); |
| 710 #ifdef DEBUG | 729 #ifdef DEBUG |
| 711 if (FLAG_enable_slow_asserts) { | 730 if (FLAG_enable_slow_asserts) { |
| 712 for (int i = 0; i < len0; i++) { | 731 for (int i = 0; i < len0; i++) { |
| 713 ASSERT(!to->get(i)->IsTheHole()); | 732 ASSERT(!to->get(i)->IsTheHole()); |
| 714 } | 733 } |
| 715 } | 734 } |
| 716 #endif | 735 #endif |
| 717 if (from == NULL) { | 736 if (from == NULL) { |
| 718 from = holder->elements(); | 737 from = holder->elements(); |
| 719 } | 738 } |
| 720 BackingStore* backing_store = BackingStore::cast(from); | |
| 721 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); | |
| 722 | 739 |
| 723 // Optimize if 'other' is empty. | 740 // Optimize if 'other' is empty. |
| 724 // We cannot optimize if 'this' is empty, as other may have holes. | 741 // We cannot optimize if 'this' is empty, as other may have holes. |
| 742 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(from); |
| 725 if (len1 == 0) return to; | 743 if (len1 == 0) return to; |
| 726 | 744 |
| 727 // Compute how many elements are not in other. | 745 // Compute how many elements are not in other. |
| 728 uint32_t extra = 0; | 746 uint32_t extra = 0; |
| 729 for (uint32_t y = 0; y < len1; y++) { | 747 for (uint32_t y = 0; y < len1; y++) { |
| 730 uint32_t key = | 748 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); |
| 731 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); | |
| 732 if (ElementsAccessorSubclass::HasElementImpl( | 749 if (ElementsAccessorSubclass::HasElementImpl( |
| 733 receiver, holder, key, backing_store)) { | 750 receiver, holder, key, from)) { |
| 734 MaybeObject* maybe_value = | 751 MaybeObject* maybe_value = |
| 735 ElementsAccessorSubclass::GetImpl(receiver, holder, | 752 ElementsAccessorSubclass::GetImpl(receiver, holder, key, from); |
| 736 key, backing_store); | |
| 737 Object* value; | 753 Object* value; |
| 738 if (!maybe_value->ToObject(&value)) return maybe_value; | 754 if (!maybe_value->To(&value)) return maybe_value; |
| 739 ASSERT(!value->IsTheHole()); | 755 ASSERT(!value->IsTheHole()); |
| 740 if (!HasKey(to, value)) { | 756 if (!HasKey(to, value)) { |
| 741 extra++; | 757 extra++; |
| 742 } | 758 } |
| 743 } | 759 } |
| 744 } | 760 } |
| 745 | 761 |
| 746 if (extra == 0) return to; | 762 if (extra == 0) return to; |
| 747 | 763 |
| 748 // Allocate the result | 764 // Allocate the result |
| 749 FixedArray* result; | 765 FixedArray* result; |
| 750 MaybeObject* maybe_obj = | 766 MaybeObject* maybe_obj = from->GetHeap()->AllocateFixedArray(len0 + extra); |
| 751 backing_store->GetHeap()->AllocateFixedArray(len0 + extra); | 767 if (!maybe_obj->To(&result)) return maybe_obj; |
| 752 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; | |
| 753 | 768 |
| 754 // Fill in the content | 769 // Fill in the content |
| 755 { | 770 { |
| 756 AssertNoAllocation no_gc; | 771 AssertNoAllocation no_gc; |
| 757 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 772 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 758 for (int i = 0; i < len0; i++) { | 773 for (int i = 0; i < len0; i++) { |
| 759 Object* e = to->get(i); | 774 Object* e = to->get(i); |
| 760 ASSERT(e->IsString() || e->IsNumber()); | 775 ASSERT(e->IsString() || e->IsNumber()); |
| 761 result->set(i, e, mode); | 776 result->set(i, e, mode); |
| 762 } | 777 } |
| 763 } | 778 } |
| 764 // Fill in the extra values. | 779 // Fill in the extra values. |
| 765 uint32_t index = 0; | 780 uint32_t index = 0; |
| 766 for (uint32_t y = 0; y < len1; y++) { | 781 for (uint32_t y = 0; y < len1; y++) { |
| 767 uint32_t key = | 782 uint32_t key = |
| 768 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); | 783 ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); |
| 769 if (ElementsAccessorSubclass::HasElementImpl( | 784 if (ElementsAccessorSubclass::HasElementImpl( |
| 770 receiver, holder, key, backing_store)) { | 785 receiver, holder, key, from)) { |
| 771 MaybeObject* maybe_value = | 786 MaybeObject* maybe_value = |
| 772 ElementsAccessorSubclass::GetImpl(receiver, holder, | 787 ElementsAccessorSubclass::GetImpl(receiver, holder, key, from); |
| 773 key, backing_store); | |
| 774 Object* value; | 788 Object* value; |
| 775 if (!maybe_value->ToObject(&value)) return maybe_value; | 789 if (!maybe_value->To(&value)) return maybe_value; |
| 776 if (!value->IsTheHole() && !HasKey(to, value)) { | 790 if (!value->IsTheHole() && !HasKey(to, value)) { |
| 777 result->set(len0 + index, value); | 791 result->set(len0 + index, value); |
| 778 index++; | 792 index++; |
| 779 } | 793 } |
| 780 } | 794 } |
| 781 } | 795 } |
| 782 ASSERT(extra == index); | 796 ASSERT(extra == index); |
| 783 return result; | 797 return result; |
| 784 } | 798 } |
| 785 | 799 |
| 786 protected: | 800 protected: |
| 787 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { | 801 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { |
| 788 return backing_store->length(); | 802 return backing_store->length(); |
| 789 } | 803 } |
| 790 | 804 |
| 791 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { | 805 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { |
| 792 return ElementsAccessorSubclass::GetCapacityImpl(backing_store); | 806 return ElementsAccessorSubclass::GetCapacityImpl(backing_store); |
| 793 } | 807 } |
| 794 | 808 |
| 795 static uint32_t GetKeyForIndexImpl(BackingStore* backing_store, | 809 static uint32_t GetKeyForIndexImpl(FixedArrayBase* backing_store, |
| 796 uint32_t index) { | 810 uint32_t index) { |
| 797 return index; | 811 return index; |
| 798 } | 812 } |
| 799 | 813 |
| 800 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, | 814 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, |
| 801 uint32_t index) { | 815 uint32_t index) { |
| 802 return ElementsAccessorSubclass::GetKeyForIndexImpl( | 816 return ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index); |
| 803 BackingStore::cast(backing_store), index); | |
| 804 } | 817 } |
| 805 | 818 |
| 806 private: | 819 private: |
| 807 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 820 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 808 }; | 821 }; |
| 809 | 822 |
| 810 | 823 |
| 811 // Super class for all fast element arrays. | 824 // Super class for all fast element arrays. |
| 812 template<typename FastElementsAccessorSubclass, | 825 template<typename FastElementsAccessorSubclass, |
| 813 typename KindTraits, | 826 typename KindTraits, |
| 814 int ElementSize> | 827 int ElementSize> |
| 815 class FastElementsAccessor | 828 class FastElementsAccessor |
| 816 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 829 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
| 817 public: | 830 public: |
| 818 explicit FastElementsAccessor(const char* name) | 831 explicit FastElementsAccessor(const char* name) |
| 819 : ElementsAccessorBase<FastElementsAccessorSubclass, | 832 : ElementsAccessorBase<FastElementsAccessorSubclass, |
| 820 KindTraits>(name) {} | 833 KindTraits>(name) {} |
| 821 protected: | 834 protected: |
| 822 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 835 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
| 823 friend class NonStrictArgumentsElementsAccessor; | 836 friend class NonStrictArgumentsElementsAccessor; |
| 824 | 837 |
| 825 typedef typename KindTraits::BackingStore BackingStore; | 838 typedef typename KindTraits::BackingStore BackingStore; |
| 826 | 839 |
| 827 // Adjusts the length of the fast backing store or returns the new length or | 840 // Adjusts the length of the fast backing store or returns the new length or |
| 828 // undefined in case conversion to a slow backing store should be performed. | 841 // undefined in case conversion to a slow backing store should be performed. |
| 829 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | 842 static MaybeObject* SetLengthWithoutNormalize(FixedArrayBase* backing_store, |
| 830 JSArray* array, | 843 JSArray* array, |
| 831 Object* length_object, | 844 Object* length_object, |
| 832 uint32_t length) { | 845 uint32_t length) { |
| 833 uint32_t old_capacity = backing_store->length(); | 846 uint32_t old_capacity = backing_store->length(); |
| 834 Object* old_length = array->length(); | 847 Object* old_length = array->length(); |
| 835 bool same_or_smaller_size = old_length->IsSmi() && | 848 bool same_or_smaller_size = old_length->IsSmi() && |
| 836 static_cast<uint32_t>(Smi::cast(old_length)->value()) >= length; | 849 static_cast<uint32_t>(Smi::cast(old_length)->value()) >= length; |
| 837 ElementsKind kind = array->GetElementsKind(); | 850 ElementsKind kind = array->GetElementsKind(); |
| 838 | 851 |
| 839 if (!same_or_smaller_size && IsFastElementsKind(kind) && | 852 if (!same_or_smaller_size && IsFastElementsKind(kind) && |
| (...skipping 17 matching lines...) Expand all Loading... |
| 857 backing_store->set_length(length); | 870 backing_store->set_length(length); |
| 858 Address filler_start = backing_store->address() + | 871 Address filler_start = backing_store->address() + |
| 859 BackingStore::OffsetOfElementAt(length); | 872 BackingStore::OffsetOfElementAt(length); |
| 860 int filler_size = (old_capacity - length) * ElementSize; | 873 int filler_size = (old_capacity - length) * ElementSize; |
| 861 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | 874 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size); |
| 862 } | 875 } |
| 863 } else { | 876 } else { |
| 864 // Otherwise, fill the unused tail with holes. | 877 // Otherwise, fill the unused tail with holes. |
| 865 int old_length = FastD2IChecked(array->length()->Number()); | 878 int old_length = FastD2IChecked(array->length()->Number()); |
| 866 for (int i = length; i < old_length; i++) { | 879 for (int i = length; i < old_length; i++) { |
| 867 backing_store->set_the_hole(i); | 880 BackingStore::cast(backing_store)->set_the_hole(i); |
| 868 } | 881 } |
| 869 } | 882 } |
| 870 return length_object; | 883 return length_object; |
| 871 } | 884 } |
| 872 | 885 |
| 873 // Check whether the backing store should be expanded. | 886 // Check whether the backing store should be expanded. |
| 874 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | 887 uint32_t min = JSObject::NewElementsCapacity(old_capacity); |
| 875 uint32_t new_capacity = length > min ? length : min; | 888 uint32_t new_capacity = length > min ? length : min; |
| 876 if (!array->ShouldConvertToSlowElements(new_capacity)) { | 889 if (!array->ShouldConvertToSlowElements(new_capacity)) { |
| 877 MaybeObject* result = FastElementsAccessorSubclass:: | 890 MaybeObject* result = FastElementsAccessorSubclass:: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 894 Heap* heap = obj->GetHeap(); | 907 Heap* heap = obj->GetHeap(); |
| 895 Object* elements = obj->elements(); | 908 Object* elements = obj->elements(); |
| 896 if (elements == heap->empty_fixed_array()) { | 909 if (elements == heap->empty_fixed_array()) { |
| 897 return heap->true_value(); | 910 return heap->true_value(); |
| 898 } | 911 } |
| 899 typename KindTraits::BackingStore* backing_store = | 912 typename KindTraits::BackingStore* backing_store = |
| 900 KindTraits::BackingStore::cast(elements); | 913 KindTraits::BackingStore::cast(elements); |
| 901 bool is_non_strict_arguments_elements_map = | 914 bool is_non_strict_arguments_elements_map = |
| 902 backing_store->map() == heap->non_strict_arguments_elements_map(); | 915 backing_store->map() == heap->non_strict_arguments_elements_map(); |
| 903 if (is_non_strict_arguments_elements_map) { | 916 if (is_non_strict_arguments_elements_map) { |
| 904 backing_store = | 917 backing_store = KindTraits::BackingStore::cast( |
| 905 KindTraits::BackingStore::cast( | 918 FixedArray::cast(backing_store)->get(1)); |
| 906 FixedArray::cast(backing_store)->get(1)); | |
| 907 } | 919 } |
| 908 uint32_t length = static_cast<uint32_t>( | 920 uint32_t length = static_cast<uint32_t>( |
| 909 obj->IsJSArray() | 921 obj->IsJSArray() |
| 910 ? Smi::cast(JSArray::cast(obj)->length())->value() | 922 ? Smi::cast(JSArray::cast(obj)->length())->value() |
| 911 : backing_store->length()); | 923 : backing_store->length()); |
| 912 if (key < length) { | 924 if (key < length) { |
| 913 if (!is_non_strict_arguments_elements_map) { | 925 if (!is_non_strict_arguments_elements_map) { |
| 914 ElementsKind kind = KindTraits::Kind; | 926 ElementsKind kind = KindTraits::Kind; |
| 915 if (IsFastPackedElementsKind(kind)) { | 927 if (IsFastPackedElementsKind(kind)) { |
| 916 MaybeObject* transitioned = | 928 MaybeObject* transitioned = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 virtual MaybeObject* Delete(JSObject* obj, | 964 virtual MaybeObject* Delete(JSObject* obj, |
| 953 uint32_t key, | 965 uint32_t key, |
| 954 JSReceiver::DeleteMode mode) { | 966 JSReceiver::DeleteMode mode) { |
| 955 return DeleteCommon(obj, key, mode); | 967 return DeleteCommon(obj, key, mode); |
| 956 } | 968 } |
| 957 | 969 |
| 958 static bool HasElementImpl( | 970 static bool HasElementImpl( |
| 959 Object* receiver, | 971 Object* receiver, |
| 960 JSObject* holder, | 972 JSObject* holder, |
| 961 uint32_t key, | 973 uint32_t key, |
| 962 typename KindTraits::BackingStore* backing_store) { | 974 FixedArrayBase* backing_store) { |
| 963 if (key >= static_cast<uint32_t>(backing_store->length())) { | 975 if (key >= static_cast<uint32_t>(backing_store->length())) { |
| 964 return false; | 976 return false; |
| 965 } | 977 } |
| 966 return !backing_store->is_the_hole(key); | 978 return !BackingStore::cast(backing_store)->is_the_hole(key); |
| 967 } | 979 } |
| 968 | 980 |
| 969 static void ValidateContents(JSObject* holder, int length) { | 981 static void ValidateContents(JSObject* holder, int length) { |
| 970 #if DEBUG | 982 #if DEBUG |
| 971 FixedArrayBase* elements = holder->elements(); | 983 FixedArrayBase* elements = holder->elements(); |
| 972 Heap* heap = elements->GetHeap(); | 984 Heap* heap = elements->GetHeap(); |
| 973 Map* map = elements->map(); | 985 Map* map = elements->map(); |
| 974 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && | 986 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && |
| 975 (map == heap->fixed_array_map() || | 987 (map == heap->fixed_array_map() || |
| 976 map == heap->fixed_cow_array_map())) || | 988 map == heap->fixed_cow_array_map())) || |
| 977 (IsFastDoubleElementsKind(KindTraits::Kind) == | 989 (IsFastDoubleElementsKind(KindTraits::Kind) == |
| 978 ((map == heap->fixed_array_map() && length == 0) || | 990 ((map == heap->fixed_array_map() && length == 0) || |
| 979 map == heap->fixed_double_array_map()))); | 991 map == heap->fixed_double_array_map()))); |
| 980 for (int i = 0; i < length; i++) { | 992 for (int i = 0; i < length; i++) { |
| 981 typename KindTraits::BackingStore* backing_store = | 993 typename KindTraits::BackingStore* backing_store = |
| 982 KindTraits::BackingStore::cast(elements); | 994 KindTraits::BackingStore::cast(elements); |
| 983 ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) || | 995 ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) || |
| 984 static_cast<Object*>(backing_store->get(i))->IsSmi()) || | 996 static_cast<Object*>(backing_store->get(i))->IsSmi()) || |
| 985 (IsFastHoleyElementsKind(KindTraits::Kind) == | 997 (IsFastHoleyElementsKind(KindTraits::Kind) == |
| 986 backing_store->is_the_hole(i))); | 998 backing_store->is_the_hole(i))); |
| 987 } | 999 } |
| 988 #endif | 1000 #endif |
| 989 } | 1001 } |
| 990 }; | 1002 }; |
| 991 | 1003 |
| 992 | 1004 |
| 1005 static ElementsKind ElementsKindForArray(FixedArrayBase* array) { |
| 1006 switch (array->map()->instance_type()) { |
| 1007 case FIXED_ARRAY_TYPE: |
| 1008 if (array->IsDictionary()) { |
| 1009 return DICTIONARY_ELEMENTS; |
| 1010 } else { |
| 1011 return FAST_HOLEY_ELEMENTS; |
| 1012 } |
| 1013 case FIXED_DOUBLE_ARRAY_TYPE: |
| 1014 return FAST_HOLEY_DOUBLE_ELEMENTS; |
| 1015 case EXTERNAL_BYTE_ARRAY_TYPE: |
| 1016 return EXTERNAL_BYTE_ELEMENTS; |
| 1017 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
| 1018 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS; |
| 1019 case EXTERNAL_SHORT_ARRAY_TYPE: |
| 1020 return EXTERNAL_SHORT_ELEMENTS; |
| 1021 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |
| 1022 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS; |
| 1023 case EXTERNAL_INT_ARRAY_TYPE: |
| 1024 return EXTERNAL_INT_ELEMENTS; |
| 1025 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: |
| 1026 return EXTERNAL_UNSIGNED_INT_ELEMENTS; |
| 1027 case EXTERNAL_FLOAT_ARRAY_TYPE: |
| 1028 return EXTERNAL_FLOAT_ELEMENTS; |
| 1029 case EXTERNAL_DOUBLE_ARRAY_TYPE: |
| 1030 return EXTERNAL_DOUBLE_ELEMENTS; |
| 1031 case EXTERNAL_PIXEL_ARRAY_TYPE: |
| 1032 return EXTERNAL_PIXEL_ELEMENTS; |
| 1033 default: |
| 1034 UNREACHABLE(); |
| 1035 } |
| 1036 return FAST_HOLEY_ELEMENTS; |
| 1037 } |
| 1038 |
| 1039 |
| 993 template<typename FastElementsAccessorSubclass, | 1040 template<typename FastElementsAccessorSubclass, |
| 994 typename KindTraits> | 1041 typename KindTraits> |
| 995 class FastSmiOrObjectElementsAccessor | 1042 class FastSmiOrObjectElementsAccessor |
| 996 : public FastElementsAccessor<FastElementsAccessorSubclass, | 1043 : public FastElementsAccessor<FastElementsAccessorSubclass, |
| 997 KindTraits, | 1044 KindTraits, |
| 998 kPointerSize> { | 1045 kPointerSize> { |
| 999 public: | 1046 public: |
| 1000 explicit FastSmiOrObjectElementsAccessor(const char* name) | 1047 explicit FastSmiOrObjectElementsAccessor(const char* name) |
| 1001 : FastElementsAccessor<FastElementsAccessorSubclass, | 1048 : FastElementsAccessor<FastElementsAccessorSubclass, |
| 1002 KindTraits, | 1049 KindTraits, |
| 1003 kPointerSize>(name) {} | 1050 kPointerSize>(name) {} |
| 1004 | 1051 |
| 1005 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1052 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 1006 uint32_t from_start, | 1053 uint32_t from_start, |
| 1007 FixedArrayBase* to, | 1054 FixedArrayBase* to, |
| 1008 ElementsKind to_kind, | 1055 ElementsKind from_kind, |
| 1009 uint32_t to_start, | 1056 uint32_t to_start, |
| 1010 int packed_size, | 1057 int packed_size, |
| 1011 int copy_size) { | 1058 int copy_size) { |
| 1012 if (IsFastSmiOrObjectElementsKind(to_kind)) { | 1059 ElementsKind to_kind = KindTraits::Kind; |
| 1013 CopyObjectToObjectElements( | 1060 switch (from_kind) { |
| 1014 FixedArray::cast(from), KindTraits::Kind, from_start, | 1061 case FAST_SMI_ELEMENTS: |
| 1015 FixedArray::cast(to), to_kind, to_start, copy_size); | 1062 case FAST_HOLEY_SMI_ELEMENTS: |
| 1016 } else if (IsFastDoubleElementsKind(to_kind)) { | 1063 case FAST_ELEMENTS: |
| 1017 if (IsFastSmiElementsKind(KindTraits::Kind)) { | 1064 case FAST_HOLEY_ELEMENTS: |
| 1018 if (IsFastPackedElementsKind(KindTraits::Kind) && | 1065 CopyObjectToObjectElements( |
| 1019 packed_size != kPackedSizeNotKnown) { | 1066 from, from_kind, from_start, to, to_kind, to_start, copy_size); |
| 1020 CopyPackedSmiToDoubleElements( | 1067 return to->GetHeap()->undefined_value(); |
| 1021 FixedArray::cast(from), from_start, | 1068 case FAST_DOUBLE_ELEMENTS: |
| 1022 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, | 1069 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1023 packed_size, copy_size); | 1070 return CopyDoubleToObjectElements( |
| 1024 } else { | 1071 from, from_start, to, to_kind, to_start, copy_size); |
| 1025 CopySmiToDoubleElements( | 1072 case DICTIONARY_ELEMENTS: |
| 1026 FixedArray::cast(from), from_start, | 1073 CopyDictionaryToObjectElements( |
| 1027 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, copy_size); | 1074 from, from_start, to, to_kind, to_start, copy_size); |
| 1028 } | 1075 return to->GetHeap()->undefined_value(); |
| 1029 } else { | 1076 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 1030 CopyObjectToDoubleElements( | 1077 // TODO(verwaest): This is a temporary hack to support extending |
| 1031 FixedArray::cast(from), from_start, | 1078 // NON_STRICT_ARGUMENTS_ELEMENTS in SetFastElementsCapacityAndLength. |
| 1032 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, copy_size); | 1079 // This case should be UNREACHABLE(). |
| 1080 FixedArray* parameter_map = FixedArray::cast(from); |
| 1081 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 1082 ElementsKind from_kind = ElementsKindForArray(arguments); |
| 1083 return CopyElementsImpl(arguments, from_start, to, from_kind, |
| 1084 to_start, packed_size, copy_size); |
| 1033 } | 1085 } |
| 1034 } else { | 1086 case EXTERNAL_BYTE_ELEMENTS: |
| 1035 UNREACHABLE(); | 1087 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 1088 case EXTERNAL_SHORT_ELEMENTS: |
| 1089 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 1090 case EXTERNAL_INT_ELEMENTS: |
| 1091 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 1092 case EXTERNAL_FLOAT_ELEMENTS: |
| 1093 case EXTERNAL_DOUBLE_ELEMENTS: |
| 1094 case EXTERNAL_PIXEL_ELEMENTS: |
| 1095 UNREACHABLE(); |
| 1036 } | 1096 } |
| 1037 return to->GetHeap()->undefined_value(); | 1097 return NULL; |
| 1038 } | 1098 } |
| 1039 | 1099 |
| 1040 | 1100 |
| 1041 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 1101 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
| 1042 uint32_t capacity, | 1102 uint32_t capacity, |
| 1043 uint32_t length) { | 1103 uint32_t length) { |
| 1044 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode = | 1104 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode = |
| 1045 obj->HasFastSmiElements() | 1105 obj->HasFastSmiElements() |
| 1046 ? JSObject::kAllowSmiElements | 1106 ? JSObject::kAllowSmiElements |
| 1047 : JSObject::kDontAllowSmiElements; | 1107 : JSObject::kDontAllowSmiElements; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 uint32_t capacity, | 1176 uint32_t capacity, |
| 1117 uint32_t length) { | 1177 uint32_t length) { |
| 1118 return obj->SetFastDoubleElementsCapacityAndLength(capacity, | 1178 return obj->SetFastDoubleElementsCapacityAndLength(capacity, |
| 1119 length); | 1179 length); |
| 1120 } | 1180 } |
| 1121 | 1181 |
| 1122 protected: | 1182 protected: |
| 1123 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1183 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 1124 uint32_t from_start, | 1184 uint32_t from_start, |
| 1125 FixedArrayBase* to, | 1185 FixedArrayBase* to, |
| 1126 ElementsKind to_kind, | 1186 ElementsKind from_kind, |
| 1127 uint32_t to_start, | 1187 uint32_t to_start, |
| 1128 int packed_size, | 1188 int packed_size, |
| 1129 int copy_size) { | 1189 int copy_size) { |
| 1130 switch (to_kind) { | 1190 switch (from_kind) { |
| 1131 case FAST_SMI_ELEMENTS: | 1191 case FAST_SMI_ELEMENTS: |
| 1132 case FAST_ELEMENTS: | 1192 CopyPackedSmiToDoubleElements( |
| 1193 from, from_start, to, to_start, packed_size, copy_size); |
| 1194 break; |
| 1133 case FAST_HOLEY_SMI_ELEMENTS: | 1195 case FAST_HOLEY_SMI_ELEMENTS: |
| 1134 case FAST_HOLEY_ELEMENTS: | 1196 CopySmiToDoubleElements(from, from_start, to, to_start, copy_size); |
| 1135 return CopyDoubleToObjectElements( | 1197 break; |
| 1136 FixedDoubleArray::castOrEmptyFixedArray(from), from_start, | |
| 1137 FixedArray::cast(to), to_kind, to_start, copy_size); | |
| 1138 case FAST_DOUBLE_ELEMENTS: | 1198 case FAST_DOUBLE_ELEMENTS: |
| 1139 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1199 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1140 CopyDoubleToDoubleElements( | 1200 CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size); |
| 1141 FixedDoubleArray::castOrEmptyFixedArray(from), from_start, | 1201 break; |
| 1142 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, copy_size); | 1202 case FAST_ELEMENTS: |
| 1143 return from; | 1203 case FAST_HOLEY_ELEMENTS: |
| 1144 default: | 1204 CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size); |
| 1205 break; |
| 1206 case DICTIONARY_ELEMENTS: |
| 1207 CopyDictionaryToDoubleElements( |
| 1208 from, from_start, to, to_start, copy_size); |
| 1209 break; |
| 1210 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 1211 case EXTERNAL_BYTE_ELEMENTS: |
| 1212 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 1213 case EXTERNAL_SHORT_ELEMENTS: |
| 1214 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 1215 case EXTERNAL_INT_ELEMENTS: |
| 1216 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 1217 case EXTERNAL_FLOAT_ELEMENTS: |
| 1218 case EXTERNAL_DOUBLE_ELEMENTS: |
| 1219 case EXTERNAL_PIXEL_ELEMENTS: |
| 1145 UNREACHABLE(); | 1220 UNREACHABLE(); |
| 1146 } | 1221 } |
| 1147 return to->GetHeap()->undefined_value(); | 1222 return to->GetHeap()->undefined_value(); |
| 1148 } | 1223 } |
| 1149 }; | 1224 }; |
| 1150 | 1225 |
| 1151 | 1226 |
| 1152 class FastPackedDoubleElementsAccessor | 1227 class FastPackedDoubleElementsAccessor |
| 1153 : public FastDoubleElementsAccessor< | 1228 : public FastDoubleElementsAccessor< |
| 1154 FastPackedDoubleElementsAccessor, | 1229 FastPackedDoubleElementsAccessor, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 | 1266 |
| 1192 protected: | 1267 protected: |
| 1193 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 1268 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
| 1194 | 1269 |
| 1195 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, | 1270 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, |
| 1196 ElementsKindTraits<Kind> >; | 1271 ElementsKindTraits<Kind> >; |
| 1197 | 1272 |
| 1198 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, | 1273 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, |
| 1199 JSObject* obj, | 1274 JSObject* obj, |
| 1200 uint32_t key, | 1275 uint32_t key, |
| 1201 BackingStore* backing_store) { | 1276 FixedArrayBase* backing_store) { |
| 1202 return | 1277 return |
| 1203 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 1278 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
| 1204 ? backing_store->get(key) | 1279 ? BackingStore::cast(backing_store)->get(key) |
| 1205 : backing_store->GetHeap()->undefined_value(); | 1280 : backing_store->GetHeap()->undefined_value(); |
| 1206 } | 1281 } |
| 1207 | 1282 |
| 1208 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( | 1283 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( |
| 1209 Object* receiver, | 1284 Object* receiver, |
| 1210 JSObject* obj, | 1285 JSObject* obj, |
| 1211 uint32_t key, | 1286 uint32_t key, |
| 1212 FixedArrayBase* backing_store) { | 1287 FixedArrayBase* backing_store) { |
| 1213 return | 1288 return |
| 1214 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 1289 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
| 1215 ? NONE : ABSENT; | 1290 ? NONE : ABSENT; |
| 1216 } | 1291 } |
| 1217 | 1292 |
| 1218 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1293 MUST_USE_RESULT static PropertyType GetTypeImpl( |
| 1219 Object* receiver, | 1294 Object* receiver, |
| 1220 JSObject* obj, | 1295 JSObject* obj, |
| 1221 uint32_t key, | 1296 uint32_t key, |
| 1222 BackingStore* backing_store) { | 1297 FixedArrayBase* backing_store) { |
| 1223 return | 1298 return |
| 1224 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) | 1299 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) |
| 1225 ? FIELD : NONEXISTENT; | 1300 ? FIELD : NONEXISTENT; |
| 1226 } | 1301 } |
| 1227 | 1302 |
| 1228 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 1303 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
| 1229 JSObject* obj, | 1304 JSObject* obj, |
| 1230 Object* length, | 1305 Object* length, |
| 1231 BackingStore* backing_store) { | 1306 FixedArrayBase* backing_store) { |
| 1232 // External arrays do not support changing their length. | 1307 // External arrays do not support changing their length. |
| 1233 UNREACHABLE(); | 1308 UNREACHABLE(); |
| 1234 return obj; | 1309 return obj; |
| 1235 } | 1310 } |
| 1236 | 1311 |
| 1237 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1312 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
| 1238 uint32_t key, | 1313 uint32_t key, |
| 1239 JSReceiver::DeleteMode mode) { | 1314 JSReceiver::DeleteMode mode) { |
| 1240 // External arrays always ignore deletes. | 1315 // External arrays always ignore deletes. |
| 1241 return obj->GetHeap()->true_value(); | 1316 return obj->GetHeap()->true_value(); |
| 1242 } | 1317 } |
| 1243 | 1318 |
| 1244 static bool HasElementImpl(Object* receiver, | 1319 static bool HasElementImpl(Object* receiver, |
| 1245 JSObject* holder, | 1320 JSObject* holder, |
| 1246 uint32_t key, | 1321 uint32_t key, |
| 1247 BackingStore* backing_store) { | 1322 FixedArrayBase* backing_store) { |
| 1248 uint32_t capacity = | 1323 uint32_t capacity = |
| 1249 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); | 1324 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); |
| 1250 return key < capacity; | 1325 return key < capacity; |
| 1251 } | 1326 } |
| 1252 }; | 1327 }; |
| 1253 | 1328 |
| 1254 | 1329 |
| 1255 class ExternalByteElementsAccessor | 1330 class ExternalByteElementsAccessor |
| 1256 : public ExternalElementsAccessor<ExternalByteElementsAccessor, | 1331 : public ExternalElementsAccessor<ExternalByteElementsAccessor, |
| 1257 EXTERNAL_BYTE_ELEMENTS> { | 1332 EXTERNAL_BYTE_ELEMENTS> { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 : public ElementsAccessorBase<DictionaryElementsAccessor, | 1421 : public ElementsAccessorBase<DictionaryElementsAccessor, |
| 1347 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | 1422 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
| 1348 public: | 1423 public: |
| 1349 explicit DictionaryElementsAccessor(const char* name) | 1424 explicit DictionaryElementsAccessor(const char* name) |
| 1350 : ElementsAccessorBase<DictionaryElementsAccessor, | 1425 : ElementsAccessorBase<DictionaryElementsAccessor, |
| 1351 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | 1426 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
| 1352 | 1427 |
| 1353 // Adjusts the length of the dictionary backing store and returns the new | 1428 // Adjusts the length of the dictionary backing store and returns the new |
| 1354 // length according to ES5 section 15.4.5.2 behavior. | 1429 // length according to ES5 section 15.4.5.2 behavior. |
| 1355 MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize( | 1430 MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize( |
| 1356 SeededNumberDictionary* dict, | 1431 FixedArrayBase* store, |
| 1357 JSArray* array, | 1432 JSArray* array, |
| 1358 Object* length_object, | 1433 Object* length_object, |
| 1359 uint32_t length) { | 1434 uint32_t length) { |
| 1435 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1360 Heap* heap = array->GetHeap(); | 1436 Heap* heap = array->GetHeap(); |
| 1361 int capacity = dict->Capacity(); | 1437 int capacity = dict->Capacity(); |
| 1362 uint32_t new_length = length; | 1438 uint32_t new_length = length; |
| 1363 uint32_t old_length = static_cast<uint32_t>(array->length()->Number()); | 1439 uint32_t old_length = static_cast<uint32_t>(array->length()->Number()); |
| 1364 if (new_length < old_length) { | 1440 if (new_length < old_length) { |
| 1365 // Find last non-deletable element in range of elements to be | 1441 // Find last non-deletable element in range of elements to be |
| 1366 // deleted and adjust range accordingly. | 1442 // deleted and adjust range accordingly. |
| 1367 for (int i = 0; i < capacity; i++) { | 1443 for (int i = 0; i < capacity; i++) { |
| 1368 Object* key = dict->KeyAt(i); | 1444 Object* key = dict->KeyAt(i); |
| 1369 if (key->IsNumber()) { | 1445 if (key->IsNumber()) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1449 } else { | 1525 } else { |
| 1450 obj->set_elements(new_elements); | 1526 obj->set_elements(new_elements); |
| 1451 } | 1527 } |
| 1452 } | 1528 } |
| 1453 return heap->true_value(); | 1529 return heap->true_value(); |
| 1454 } | 1530 } |
| 1455 | 1531 |
| 1456 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1532 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 1457 uint32_t from_start, | 1533 uint32_t from_start, |
| 1458 FixedArrayBase* to, | 1534 FixedArrayBase* to, |
| 1459 ElementsKind to_kind, | 1535 ElementsKind from_kind, |
| 1460 uint32_t to_start, | 1536 uint32_t to_start, |
| 1461 int packed_size, | 1537 int packed_size, |
| 1462 int copy_size) { | 1538 int copy_size) { |
| 1463 switch (to_kind) { | 1539 UNREACHABLE(); |
| 1464 case FAST_SMI_ELEMENTS: | 1540 return NULL; |
| 1465 case FAST_ELEMENTS: | |
| 1466 case FAST_HOLEY_SMI_ELEMENTS: | |
| 1467 case FAST_HOLEY_ELEMENTS: | |
| 1468 CopyDictionaryToObjectElements( | |
| 1469 SeededNumberDictionary::cast(from), from_start, | |
| 1470 FixedArray::cast(to), to_kind, to_start, copy_size); | |
| 1471 return from; | |
| 1472 case FAST_DOUBLE_ELEMENTS: | |
| 1473 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 1474 CopyDictionaryToDoubleElements( | |
| 1475 SeededNumberDictionary::cast(from), from_start, | |
| 1476 FixedDoubleArray::castOrEmptyFixedArray(to), to_start, | |
| 1477 copy_size); | |
| 1478 return from; | |
| 1479 default: | |
| 1480 UNREACHABLE(); | |
| 1481 } | |
| 1482 return to->GetHeap()->undefined_value(); | |
| 1483 } | 1541 } |
| 1484 | 1542 |
| 1485 | 1543 |
| 1486 protected: | 1544 protected: |
| 1487 friend class ElementsAccessorBase<DictionaryElementsAccessor, | 1545 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
| 1488 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | 1546 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
| 1489 | 1547 |
| 1490 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1548 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
| 1491 uint32_t key, | 1549 uint32_t key, |
| 1492 JSReceiver::DeleteMode mode) { | 1550 JSReceiver::DeleteMode mode) { |
| 1493 return DeleteCommon(obj, key, mode); | 1551 return DeleteCommon(obj, key, mode); |
| 1494 } | 1552 } |
| 1495 | 1553 |
| 1496 MUST_USE_RESULT static MaybeObject* GetImpl( | 1554 MUST_USE_RESULT static MaybeObject* GetImpl( |
| 1497 Object* receiver, | 1555 Object* receiver, |
| 1498 JSObject* obj, | 1556 JSObject* obj, |
| 1499 uint32_t key, | 1557 uint32_t key, |
| 1500 SeededNumberDictionary* backing_store) { | 1558 FixedArrayBase* store) { |
| 1559 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
| 1501 int entry = backing_store->FindEntry(key); | 1560 int entry = backing_store->FindEntry(key); |
| 1502 if (entry != SeededNumberDictionary::kNotFound) { | 1561 if (entry != SeededNumberDictionary::kNotFound) { |
| 1503 Object* element = backing_store->ValueAt(entry); | 1562 Object* element = backing_store->ValueAt(entry); |
| 1504 PropertyDetails details = backing_store->DetailsAt(entry); | 1563 PropertyDetails details = backing_store->DetailsAt(entry); |
| 1505 if (details.type() == CALLBACKS) { | 1564 if (details.type() == CALLBACKS) { |
| 1506 return obj->GetElementWithCallback(receiver, | 1565 return obj->GetElementWithCallback(receiver, |
| 1507 element, | 1566 element, |
| 1508 key, | 1567 key, |
| 1509 obj); | 1568 obj); |
| 1510 } else { | 1569 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1525 if (entry != SeededNumberDictionary::kNotFound) { | 1584 if (entry != SeededNumberDictionary::kNotFound) { |
| 1526 return dictionary->DetailsAt(entry).attributes(); | 1585 return dictionary->DetailsAt(entry).attributes(); |
| 1527 } | 1586 } |
| 1528 return ABSENT; | 1587 return ABSENT; |
| 1529 } | 1588 } |
| 1530 | 1589 |
| 1531 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1590 MUST_USE_RESULT static PropertyType GetTypeImpl( |
| 1532 Object* receiver, | 1591 Object* receiver, |
| 1533 JSObject* obj, | 1592 JSObject* obj, |
| 1534 uint32_t key, | 1593 uint32_t key, |
| 1535 SeededNumberDictionary* backing_store) { | 1594 FixedArrayBase* store) { |
| 1595 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
| 1536 int entry = backing_store->FindEntry(key); | 1596 int entry = backing_store->FindEntry(key); |
| 1537 if (entry != SeededNumberDictionary::kNotFound) { | 1597 if (entry != SeededNumberDictionary::kNotFound) { |
| 1538 return backing_store->DetailsAt(entry).type(); | 1598 return backing_store->DetailsAt(entry).type(); |
| 1539 } | 1599 } |
| 1540 return NONEXISTENT; | 1600 return NONEXISTENT; |
| 1541 } | 1601 } |
| 1542 | 1602 |
| 1543 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 1603 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
| 1544 Object* receiver, | 1604 Object* receiver, |
| 1545 JSObject* obj, | 1605 JSObject* obj, |
| 1546 uint32_t key, | 1606 uint32_t key, |
| 1547 BackingStore* backing_store) { | 1607 FixedArrayBase* store) { |
| 1608 SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store); |
| 1548 int entry = backing_store->FindEntry(key); | 1609 int entry = backing_store->FindEntry(key); |
| 1549 if (entry != SeededNumberDictionary::kNotFound && | 1610 if (entry != SeededNumberDictionary::kNotFound && |
| 1550 backing_store->DetailsAt(entry).type() == CALLBACKS && | 1611 backing_store->DetailsAt(entry).type() == CALLBACKS && |
| 1551 backing_store->ValueAt(entry)->IsAccessorPair()) { | 1612 backing_store->ValueAt(entry)->IsAccessorPair()) { |
| 1552 return AccessorPair::cast(backing_store->ValueAt(entry)); | 1613 return AccessorPair::cast(backing_store->ValueAt(entry)); |
| 1553 } | 1614 } |
| 1554 return NULL; | 1615 return NULL; |
| 1555 } | 1616 } |
| 1556 | 1617 |
| 1557 static bool HasElementImpl(Object* receiver, | 1618 static bool HasElementImpl(Object* receiver, |
| 1558 JSObject* holder, | 1619 JSObject* holder, |
| 1559 uint32_t key, | 1620 uint32_t key, |
| 1560 SeededNumberDictionary* backing_store) { | 1621 FixedArrayBase* backing_store) { |
| 1561 return backing_store->FindEntry(key) != | 1622 return SeededNumberDictionary::cast(backing_store)->FindEntry(key) != |
| 1562 SeededNumberDictionary::kNotFound; | 1623 SeededNumberDictionary::kNotFound; |
| 1563 } | 1624 } |
| 1564 | 1625 |
| 1565 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, | 1626 static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, |
| 1566 uint32_t index) { | 1627 uint32_t index) { |
| 1628 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1567 Object* key = dict->KeyAt(index); | 1629 Object* key = dict->KeyAt(index); |
| 1568 return Smi::cast(key)->value(); | 1630 return Smi::cast(key)->value(); |
| 1569 } | 1631 } |
| 1570 }; | 1632 }; |
| 1571 | 1633 |
| 1572 | 1634 |
| 1573 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< | 1635 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< |
| 1574 NonStrictArgumentsElementsAccessor, | 1636 NonStrictArgumentsElementsAccessor, |
| 1575 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { | 1637 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { |
| 1576 public: | 1638 public: |
| 1577 explicit NonStrictArgumentsElementsAccessor(const char* name) | 1639 explicit NonStrictArgumentsElementsAccessor(const char* name) |
| 1578 : ElementsAccessorBase< | 1640 : ElementsAccessorBase< |
| 1579 NonStrictArgumentsElementsAccessor, | 1641 NonStrictArgumentsElementsAccessor, |
| 1580 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} | 1642 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} |
| 1581 protected: | 1643 protected: |
| 1582 friend class ElementsAccessorBase< | 1644 friend class ElementsAccessorBase< |
| 1583 NonStrictArgumentsElementsAccessor, | 1645 NonStrictArgumentsElementsAccessor, |
| 1584 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; | 1646 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; |
| 1585 | 1647 |
| 1586 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, | 1648 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, |
| 1587 JSObject* obj, | 1649 JSObject* obj, |
| 1588 uint32_t key, | 1650 uint32_t key, |
| 1589 FixedArray* parameter_map) { | 1651 FixedArrayBase* parameters) { |
| 1652 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1590 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1653 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
| 1591 if (!probe->IsTheHole()) { | 1654 if (!probe->IsTheHole()) { |
| 1592 Context* context = Context::cast(parameter_map->get(0)); | 1655 Context* context = Context::cast(parameter_map->get(0)); |
| 1593 int context_index = Smi::cast(probe)->value(); | 1656 int context_index = Smi::cast(probe)->value(); |
| 1594 ASSERT(!context->get(context_index)->IsTheHole()); | 1657 ASSERT(!context->get(context_index)->IsTheHole()); |
| 1595 return context->get(context_index); | 1658 return context->get(context_index); |
| 1596 } else { | 1659 } else { |
| 1597 // Object is not mapped, defer to the arguments. | 1660 // Object is not mapped, defer to the arguments. |
| 1598 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1661 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1599 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( | 1662 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1627 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1690 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1628 return ElementsAccessor::ForArray(arguments)->GetAttributes( | 1691 return ElementsAccessor::ForArray(arguments)->GetAttributes( |
| 1629 receiver, obj, key, arguments); | 1692 receiver, obj, key, arguments); |
| 1630 } | 1693 } |
| 1631 } | 1694 } |
| 1632 | 1695 |
| 1633 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1696 MUST_USE_RESULT static PropertyType GetTypeImpl( |
| 1634 Object* receiver, | 1697 Object* receiver, |
| 1635 JSObject* obj, | 1698 JSObject* obj, |
| 1636 uint32_t key, | 1699 uint32_t key, |
| 1637 FixedArray* parameter_map) { | 1700 FixedArrayBase* parameters) { |
| 1701 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1638 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1702 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
| 1639 if (!probe->IsTheHole()) { | 1703 if (!probe->IsTheHole()) { |
| 1640 return FIELD; | 1704 return FIELD; |
| 1641 } else { | 1705 } else { |
| 1642 // If not aliased, check the arguments. | 1706 // If not aliased, check the arguments. |
| 1643 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1707 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1644 return ElementsAccessor::ForArray(arguments)->GetType( | 1708 return ElementsAccessor::ForArray(arguments)->GetType( |
| 1645 receiver, obj, key, arguments); | 1709 receiver, obj, key, arguments); |
| 1646 } | 1710 } |
| 1647 } | 1711 } |
| 1648 | 1712 |
| 1649 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 1713 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
| 1650 Object* receiver, | 1714 Object* receiver, |
| 1651 JSObject* obj, | 1715 JSObject* obj, |
| 1652 uint32_t key, | 1716 uint32_t key, |
| 1653 FixedArray* parameter_map) { | 1717 FixedArrayBase* parameters) { |
| 1718 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1654 Object* probe = GetParameterMapArg(obj, parameter_map, key); | 1719 Object* probe = GetParameterMapArg(obj, parameter_map, key); |
| 1655 if (!probe->IsTheHole()) { | 1720 if (!probe->IsTheHole()) { |
| 1656 return NULL; | 1721 return NULL; |
| 1657 } else { | 1722 } else { |
| 1658 // If not aliased, check the arguments. | 1723 // If not aliased, check the arguments. |
| 1659 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1724 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1660 return ElementsAccessor::ForArray(arguments)->GetAccessorPair( | 1725 return ElementsAccessor::ForArray(arguments)->GetAccessorPair( |
| 1661 receiver, obj, key, arguments); | 1726 receiver, obj, key, arguments); |
| 1662 } | 1727 } |
| 1663 } | 1728 } |
| 1664 | 1729 |
| 1665 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 1730 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
| 1666 JSObject* obj, | 1731 JSObject* obj, |
| 1667 Object* length, | 1732 Object* length, |
| 1668 FixedArray* parameter_map) { | 1733 FixedArrayBase* parameter_map) { |
| 1669 // TODO(mstarzinger): This was never implemented but will be used once we | 1734 // TODO(mstarzinger): This was never implemented but will be used once we |
| 1670 // correctly implement [[DefineOwnProperty]] on arrays. | 1735 // correctly implement [[DefineOwnProperty]] on arrays. |
| 1671 UNIMPLEMENTED(); | 1736 UNIMPLEMENTED(); |
| 1672 return obj; | 1737 return obj; |
| 1673 } | 1738 } |
| 1674 | 1739 |
| 1675 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1740 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
| 1676 uint32_t key, | 1741 uint32_t key, |
| 1677 JSReceiver::DeleteMode mode) { | 1742 JSReceiver::DeleteMode mode) { |
| 1678 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 1743 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1692 // the class for the most generalized ElementsKind subclass. | 1757 // the class for the most generalized ElementsKind subclass. |
| 1693 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode); | 1758 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode); |
| 1694 } | 1759 } |
| 1695 } | 1760 } |
| 1696 return obj->GetHeap()->true_value(); | 1761 return obj->GetHeap()->true_value(); |
| 1697 } | 1762 } |
| 1698 | 1763 |
| 1699 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1764 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
| 1700 uint32_t from_start, | 1765 uint32_t from_start, |
| 1701 FixedArrayBase* to, | 1766 FixedArrayBase* to, |
| 1702 ElementsKind to_kind, | 1767 ElementsKind from_kind, |
| 1703 uint32_t to_start, | 1768 uint32_t to_start, |
| 1704 int packed_size, | 1769 int packed_size, |
| 1705 int copy_size) { | 1770 int copy_size) { |
| 1706 FixedArray* parameter_map = FixedArray::cast(from); | 1771 UNREACHABLE(); |
| 1707 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1772 return NULL; |
| 1708 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); | |
| 1709 return accessor->CopyElements(NULL, from_start, to, to_kind, | |
| 1710 to_start, copy_size, arguments); | |
| 1711 } | 1773 } |
| 1712 | 1774 |
| 1713 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { | 1775 static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) { |
| 1714 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1776 FixedArray* parameter_map = FixedArray::cast(backing_store); |
| 1715 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1777 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 1716 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 1778 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
| 1717 ForArray(arguments)->GetCapacity(arguments)); | 1779 ForArray(arguments)->GetCapacity(arguments)); |
| 1718 } | 1780 } |
| 1719 | 1781 |
| 1720 static uint32_t GetKeyForIndexImpl(FixedArray* dict, | 1782 static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, |
| 1721 uint32_t index) { | 1783 uint32_t index) { |
| 1722 return index; | 1784 return index; |
| 1723 } | 1785 } |
| 1724 | 1786 |
| 1725 static bool HasElementImpl(Object* receiver, | 1787 static bool HasElementImpl(Object* receiver, |
| 1726 JSObject* holder, | 1788 JSObject* holder, |
| 1727 uint32_t key, | 1789 uint32_t key, |
| 1728 FixedArray* parameter_map) { | 1790 FixedArrayBase* parameters) { |
| 1791 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1729 Object* probe = GetParameterMapArg(holder, parameter_map, key); | 1792 Object* probe = GetParameterMapArg(holder, parameter_map, key); |
| 1730 if (!probe->IsTheHole()) { | 1793 if (!probe->IsTheHole()) { |
| 1731 return true; | 1794 return true; |
| 1732 } else { | 1795 } else { |
| 1733 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1796 FixedArrayBase* arguments = |
| 1797 FixedArrayBase::cast(FixedArray::cast(parameter_map)->get(1)); |
| 1734 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); | 1798 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); |
| 1735 return !accessor->Get(receiver, holder, key, arguments)->IsTheHole(); | 1799 return !accessor->Get(receiver, holder, key, arguments)->IsTheHole(); |
| 1736 } | 1800 } |
| 1737 } | 1801 } |
| 1738 | 1802 |
| 1739 private: | 1803 private: |
| 1740 static Object* GetParameterMapArg(JSObject* holder, | 1804 static Object* GetParameterMapArg(JSObject* holder, |
| 1741 FixedArray* parameter_map, | 1805 FixedArray* parameter_map, |
| 1742 uint32_t key) { | 1806 uint32_t key) { |
| 1743 uint32_t length = holder->IsJSArray() | 1807 uint32_t length = holder->IsJSArray() |
| 1744 ? Smi::cast(JSArray::cast(holder)->length())->value() | 1808 ? Smi::cast(JSArray::cast(holder)->length())->value() |
| 1745 : parameter_map->length(); | 1809 : parameter_map->length(); |
| 1746 return key < (length - 2 ) | 1810 return key < (length - 2) |
| 1747 ? parameter_map->get(key + 2) | 1811 ? parameter_map->get(key + 2) |
| 1748 : parameter_map->GetHeap()->the_hole_value(); | 1812 : parameter_map->GetHeap()->the_hole_value(); |
| 1749 } | 1813 } |
| 1750 }; | 1814 }; |
| 1751 | 1815 |
| 1752 | 1816 |
| 1753 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1817 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { |
| 1754 switch (array->map()->instance_type()) { | 1818 return elements_accessors_[ElementsKindForArray(array)]; |
| 1755 case FIXED_ARRAY_TYPE: | |
| 1756 if (array->IsDictionary()) { | |
| 1757 return elements_accessors_[DICTIONARY_ELEMENTS]; | |
| 1758 } else { | |
| 1759 return elements_accessors_[FAST_HOLEY_ELEMENTS]; | |
| 1760 } | |
| 1761 case EXTERNAL_BYTE_ARRAY_TYPE: | |
| 1762 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS]; | |
| 1763 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | |
| 1764 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS]; | |
| 1765 case EXTERNAL_SHORT_ARRAY_TYPE: | |
| 1766 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS]; | |
| 1767 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: | |
| 1768 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS]; | |
| 1769 case EXTERNAL_INT_ARRAY_TYPE: | |
| 1770 return elements_accessors_[EXTERNAL_INT_ELEMENTS]; | |
| 1771 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: | |
| 1772 return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS]; | |
| 1773 case EXTERNAL_FLOAT_ARRAY_TYPE: | |
| 1774 return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS]; | |
| 1775 case EXTERNAL_DOUBLE_ARRAY_TYPE: | |
| 1776 return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS]; | |
| 1777 case EXTERNAL_PIXEL_ARRAY_TYPE: | |
| 1778 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS]; | |
| 1779 default: | |
| 1780 UNREACHABLE(); | |
| 1781 return NULL; | |
| 1782 } | |
| 1783 } | 1819 } |
| 1784 | 1820 |
| 1785 | 1821 |
| 1786 void ElementsAccessor::InitializeOncePerProcess() { | 1822 void ElementsAccessor::InitializeOncePerProcess() { |
| 1787 static ElementsAccessor* accessor_array[] = { | 1823 static ElementsAccessor* accessor_array[] = { |
| 1788 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), | 1824 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), |
| 1789 ELEMENTS_LIST(ACCESSOR_ARRAY) | 1825 ELEMENTS_LIST(ACCESSOR_ARRAY) |
| 1790 #undef ACCESSOR_ARRAY | 1826 #undef ACCESSOR_ARRAY |
| 1791 }; | 1827 }; |
| 1792 | 1828 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1803 #undef ACCESSOR_DELETE | 1839 #undef ACCESSOR_DELETE |
| 1804 elements_accessors_ = NULL; | 1840 elements_accessors_ = NULL; |
| 1805 } | 1841 } |
| 1806 | 1842 |
| 1807 | 1843 |
| 1808 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | 1844 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
| 1809 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, | 1845 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, |
| 1810 ElementsKindTraits>:: | 1846 ElementsKindTraits>:: |
| 1811 SetLengthImpl(JSObject* obj, | 1847 SetLengthImpl(JSObject* obj, |
| 1812 Object* length, | 1848 Object* length, |
| 1813 typename ElementsKindTraits::BackingStore* backing_store) { | 1849 FixedArrayBase* backing_store) { |
| 1814 JSArray* array = JSArray::cast(obj); | 1850 JSArray* array = JSArray::cast(obj); |
| 1815 | 1851 |
| 1816 // Fast case: The new length fits into a Smi. | 1852 // Fast case: The new length fits into a Smi. |
| 1817 MaybeObject* maybe_smi_length = length->ToSmi(); | 1853 MaybeObject* maybe_smi_length = length->ToSmi(); |
| 1818 Object* smi_length = Smi::FromInt(0); | 1854 Object* smi_length = Smi::FromInt(0); |
| 1819 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 1855 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 1820 const int value = Smi::cast(smi_length)->value(); | 1856 const int value = Smi::cast(smi_length)->value(); |
| 1821 if (value >= 0) { | 1857 if (value >= 0) { |
| 1822 Object* new_length; | 1858 Object* new_length; |
| 1823 MaybeObject* result = ElementsAccessorSubclass:: | 1859 MaybeObject* result = ElementsAccessorSubclass:: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1860 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1896 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
| 1861 new_backing_store->set(0, length); | 1897 new_backing_store->set(0, length); |
| 1862 { MaybeObject* result = array->SetContent(new_backing_store); | 1898 { MaybeObject* result = array->SetContent(new_backing_store); |
| 1863 if (result->IsFailure()) return result; | 1899 if (result->IsFailure()) return result; |
| 1864 } | 1900 } |
| 1865 return array; | 1901 return array; |
| 1866 } | 1902 } |
| 1867 | 1903 |
| 1868 | 1904 |
| 1869 } } // namespace v8::internal | 1905 } } // namespace v8::internal |
| OLD | NEW |