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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 // constant function properties. | 324 // constant function properties. |
325 if (should_transform && !has_function_literal) { | 325 if (should_transform && !has_function_literal) { |
326 JSObject::TransformToFastProperties( | 326 JSObject::TransformToFastProperties( |
327 boilerplate, boilerplate->map()->unused_property_fields()); | 327 boilerplate, boilerplate->map()->unused_property_fields()); |
328 } | 328 } |
329 | 329 |
330 return boilerplate; | 330 return boilerplate; |
331 } | 331 } |
332 | 332 |
333 | 333 |
334 MaybeObject* TransitionElements(Handle<Object> object, | 334 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements( |
335 ElementsKind to_kind, | 335 Handle<Object> object, |
336 Isolate* isolate) { | 336 ElementsKind to_kind, |
| 337 Isolate* isolate) { |
337 HandleScope scope(isolate); | 338 HandleScope scope(isolate); |
338 if (!object->IsJSObject()) return isolate->ThrowIllegalOperation(); | 339 if (!object->IsJSObject()) { |
| 340 isolate->ThrowIllegalOperation(); |
| 341 return MaybeHandle<Object>(); |
| 342 } |
339 ElementsKind from_kind = | 343 ElementsKind from_kind = |
340 Handle<JSObject>::cast(object)->map()->elements_kind(); | 344 Handle<JSObject>::cast(object)->map()->elements_kind(); |
341 if (Map::IsValidElementsTransition(from_kind, to_kind)) { | 345 if (Map::IsValidElementsTransition(from_kind, to_kind)) { |
342 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind); | 346 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind); |
343 return *object; | 347 return object; |
344 } | 348 } |
345 return isolate->ThrowIllegalOperation(); | 349 isolate->ThrowIllegalOperation(); |
| 350 return MaybeHandle<Object>(); |
346 } | 351 } |
347 | 352 |
348 | 353 |
349 static const int kSmiLiteralMinimumLength = 1024; | 354 static const int kSmiLiteralMinimumLength = 1024; |
350 | 355 |
351 | 356 |
352 MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate( | 357 MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate( |
353 Isolate* isolate, | 358 Isolate* isolate, |
354 Handle<FixedArray> literals, | 359 Handle<FixedArray> literals, |
355 Handle<FixedArray> elements) { | 360 Handle<FixedArray> elements) { |
356 // Create the JSArray. | 361 // Create the JSArray. |
357 Handle<JSFunction> constructor( | 362 Handle<JSFunction> constructor( |
358 JSFunction::NativeContextFromLiterals(*literals)->array_function()); | 363 JSFunction::NativeContextFromLiterals(*literals)->array_function()); |
359 | 364 |
360 PretenureFlag pretenure_flag = | 365 PretenureFlag pretenure_flag = |
361 isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED; | 366 isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED; |
362 | 367 |
363 Handle<JSArray> object = Handle<JSArray>::cast( | 368 Handle<JSArray> object = Handle<JSArray>::cast( |
364 isolate->factory()->NewJSObject(constructor, pretenure_flag)); | 369 isolate->factory()->NewJSObject(constructor, pretenure_flag)); |
365 | 370 |
366 ElementsKind constant_elements_kind = | 371 ElementsKind constant_elements_kind = |
367 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); | 372 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); |
368 Handle<FixedArrayBase> constant_elements_values( | 373 Handle<FixedArrayBase> constant_elements_values( |
369 FixedArrayBase::cast(elements->get(1))); | 374 FixedArrayBase::cast(elements->get(1))); |
370 | 375 |
371 ASSERT(IsFastElementsKind(constant_elements_kind)); | 376 { DisallowHeapAllocation no_gc; |
372 Context* native_context = isolate->context()->native_context(); | 377 ASSERT(IsFastElementsKind(constant_elements_kind)); |
373 Object* maybe_maps_array = native_context->js_array_maps(); | 378 Context* native_context = isolate->context()->native_context(); |
374 ASSERT(!maybe_maps_array->IsUndefined()); | 379 Object* maps_array = native_context->js_array_maps(); |
375 Object* maybe_map = FixedArray::cast(maybe_maps_array)->get( | 380 ASSERT(!maps_array->IsUndefined()); |
376 constant_elements_kind); | 381 Object* map = FixedArray::cast(maps_array)->get(constant_elements_kind); |
377 ASSERT(maybe_map->IsMap()); | 382 object->set_map(Map::cast(map)); |
378 object->set_map(Map::cast(maybe_map)); | 383 } |
379 | 384 |
380 Handle<FixedArrayBase> copied_elements_values; | 385 Handle<FixedArrayBase> copied_elements_values; |
381 if (IsFastDoubleElementsKind(constant_elements_kind)) { | 386 if (IsFastDoubleElementsKind(constant_elements_kind)) { |
382 ASSERT(FLAG_smi_only_arrays); | 387 ASSERT(FLAG_smi_only_arrays); |
383 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( | 388 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( |
384 Handle<FixedDoubleArray>::cast(constant_elements_values)); | 389 Handle<FixedDoubleArray>::cast(constant_elements_values)); |
385 } else { | 390 } else { |
386 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind)); | 391 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind)); |
387 const bool is_cow = | 392 const bool is_cow = |
388 (constant_elements_values->map() == | 393 (constant_elements_values->map() == |
389 isolate->heap()->fixed_cow_array_map()); | 394 isolate->heap()->fixed_cow_array_map()); |
390 if (is_cow) { | 395 if (is_cow) { |
391 copied_elements_values = constant_elements_values; | 396 copied_elements_values = constant_elements_values; |
392 #if DEBUG | 397 #if DEBUG |
393 Handle<FixedArray> fixed_array_values = | 398 Handle<FixedArray> fixed_array_values = |
394 Handle<FixedArray>::cast(copied_elements_values); | 399 Handle<FixedArray>::cast(copied_elements_values); |
395 for (int i = 0; i < fixed_array_values->length(); i++) { | 400 for (int i = 0; i < fixed_array_values->length(); i++) { |
396 ASSERT(!fixed_array_values->get(i)->IsFixedArray()); | 401 ASSERT(!fixed_array_values->get(i)->IsFixedArray()); |
397 } | 402 } |
398 #endif | 403 #endif |
399 } else { | 404 } else { |
400 Handle<FixedArray> fixed_array_values = | 405 Handle<FixedArray> fixed_array_values = |
401 Handle<FixedArray>::cast(constant_elements_values); | 406 Handle<FixedArray>::cast(constant_elements_values); |
402 Handle<FixedArray> fixed_array_values_copy = | 407 Handle<FixedArray> fixed_array_values_copy = |
403 isolate->factory()->CopyFixedArray(fixed_array_values); | 408 isolate->factory()->CopyFixedArray(fixed_array_values); |
404 copied_elements_values = fixed_array_values_copy; | 409 copied_elements_values = fixed_array_values_copy; |
405 for (int i = 0; i < fixed_array_values->length(); i++) { | 410 for (int i = 0; i < fixed_array_values->length(); i++) { |
406 Object* current = fixed_array_values->get(i); | 411 if (fixed_array_values->get(i)->IsFixedArray()) { |
407 if (current->IsFixedArray()) { | |
408 // The value contains the constant_properties of a | 412 // The value contains the constant_properties of a |
409 // simple object or array literal. | 413 // simple object or array literal. |
410 Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i))); | 414 Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i))); |
411 Handle<Object> result; | 415 Handle<Object> result; |
412 ASSIGN_RETURN_ON_EXCEPTION( | 416 ASSIGN_RETURN_ON_EXCEPTION( |
413 isolate, result, | 417 isolate, result, |
414 CreateLiteralBoilerplate(isolate, literals, fa), | 418 CreateLiteralBoilerplate(isolate, literals, fa), |
415 Object); | 419 Object); |
416 fixed_array_values_copy->set(i, *result); | 420 fixed_array_values_copy->set(i, *result); |
417 } | 421 } |
418 } | 422 } |
419 } | 423 } |
420 } | 424 } |
421 object->set_elements(*copied_elements_values); | 425 object->set_elements(*copied_elements_values); |
422 object->set_length(Smi::FromInt(copied_elements_values->length())); | 426 object->set_length(Smi::FromInt(copied_elements_values->length())); |
423 | 427 |
424 // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is | 428 // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is |
425 // on or the object is larger than the threshold. | 429 // on or the object is larger than the threshold. |
426 if (!FLAG_smi_only_arrays && | 430 if (!FLAG_smi_only_arrays && |
427 constant_elements_values->length() < kSmiLiteralMinimumLength) { | 431 constant_elements_values->length() < kSmiLiteralMinimumLength) { |
428 ElementsKind elements_kind = object->GetElementsKind(); | 432 ElementsKind elements_kind = object->GetElementsKind(); |
429 if (!IsFastObjectElementsKind(elements_kind)) { | 433 if (!IsFastObjectElementsKind(elements_kind)) { |
430 if (IsFastHoleyElementsKind(elements_kind)) { | 434 if (IsFastHoleyElementsKind(elements_kind)) { |
431 CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS, | 435 TransitionElements(object, FAST_HOLEY_ELEMENTS, isolate).Check(); |
432 isolate)->IsFailure()); | |
433 } else { | 436 } else { |
434 CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure()); | 437 TransitionElements(object, FAST_ELEMENTS, isolate).Check(); |
435 } | 438 } |
436 } | 439 } |
437 } | 440 } |
438 | 441 |
439 JSObject::ValidateElements(object); | 442 JSObject::ValidateElements(object); |
440 return object; | 443 return object; |
441 } | 444 } |
442 | 445 |
443 | 446 |
444 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( | 447 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( |
(...skipping 4624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5069 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) { | 5072 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) { |
5070 // JSObject without a name key. If the key is a Smi, check for a | 5073 // JSObject without a name key. If the key is a Smi, check for a |
5071 // definite out-of-bounds access to elements, which is a strong indicator | 5074 // definite out-of-bounds access to elements, which is a strong indicator |
5072 // that subsequent accesses will also call the runtime. Proactively | 5075 // that subsequent accesses will also call the runtime. Proactively |
5073 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of | 5076 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of |
5074 // doubles for those future calls in the case that the elements would | 5077 // doubles for those future calls in the case that the elements would |
5075 // become FAST_DOUBLE_ELEMENTS. | 5078 // become FAST_DOUBLE_ELEMENTS. |
5076 Handle<JSObject> js_object(args.at<JSObject>(0)); | 5079 Handle<JSObject> js_object(args.at<JSObject>(0)); |
5077 ElementsKind elements_kind = js_object->GetElementsKind(); | 5080 ElementsKind elements_kind = js_object->GetElementsKind(); |
5078 if (IsFastDoubleElementsKind(elements_kind)) { | 5081 if (IsFastDoubleElementsKind(elements_kind)) { |
5079 FixedArrayBase* elements = js_object->elements(); | 5082 if (args.at<Smi>(1)->value() >= js_object->elements()->length()) { |
5080 if (args.at<Smi>(1)->value() >= elements->length()) { | |
5081 if (IsFastHoleyElementsKind(elements_kind)) { | 5083 if (IsFastHoleyElementsKind(elements_kind)) { |
5082 elements_kind = FAST_HOLEY_ELEMENTS; | 5084 elements_kind = FAST_HOLEY_ELEMENTS; |
5083 } else { | 5085 } else { |
5084 elements_kind = FAST_ELEMENTS; | 5086 elements_kind = FAST_ELEMENTS; |
5085 } | 5087 } |
5086 MaybeObject* maybe_object = TransitionElements(js_object, | 5088 RETURN_FAILURE_ON_EXCEPTION( |
5087 elements_kind, | 5089 isolate, TransitionElements(js_object, elements_kind, isolate)); |
5088 isolate); | |
5089 if (maybe_object->IsFailure()) return maybe_object; | |
5090 } | 5090 } |
5091 } else { | 5091 } else { |
5092 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || | 5092 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || |
5093 !IsFastElementsKind(elements_kind)); | 5093 !IsFastElementsKind(elements_kind)); |
5094 } | 5094 } |
5095 } | 5095 } |
5096 } else if (args[0]->IsString() && args[1]->IsSmi()) { | 5096 } else if (args[0]->IsString() && args[1]->IsSmi()) { |
5097 // Fast case for string indexing using [] with a smi index. | 5097 // Fast case for string indexing using [] with a smi index. |
5098 HandleScope scope(isolate); | 5098 HandleScope scope(isolate); |
5099 Handle<String> str = args.at<String>(0); | 5099 Handle<String> str = args.at<String>(0); |
(...skipping 10161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15261 } | 15261 } |
15262 } | 15262 } |
15263 | 15263 |
15264 | 15264 |
15265 void Runtime::OutOfMemory() { | 15265 void Runtime::OutOfMemory() { |
15266 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); | 15266 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); |
15267 UNREACHABLE(); | 15267 UNREACHABLE(); |
15268 } | 15268 } |
15269 | 15269 |
15270 } } // namespace v8::internal | 15270 } } // namespace v8::internal |
OLD | NEW |