| 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 if (!maybe_result->ToObject(&result)) return maybe_result; | 201 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 202 } | 202 } |
| 203 } | 203 } |
| 204 } | 204 } |
| 205 } | 205 } |
| 206 | 206 |
| 207 // Deep copy local elements. | 207 // Deep copy local elements. |
| 208 // Pixel elements cannot be created using an object literal. | 208 // Pixel elements cannot be created using an object literal. |
| 209 ASSERT(!copy->HasExternalArrayElements()); | 209 ASSERT(!copy->HasExternalArrayElements()); |
| 210 switch (copy->GetElementsKind()) { | 210 switch (copy->GetElementsKind()) { |
| 211 case FAST_SMI_ONLY_ELEMENTS: | 211 case FAST_SMI_ELEMENTS: |
| 212 case FAST_ELEMENTS: { | 212 case FAST_ELEMENTS: |
| 213 case FAST_HOLEY_SMI_ELEMENTS: |
| 214 case FAST_HOLEY_ELEMENTS: { |
| 213 FixedArray* elements = FixedArray::cast(copy->elements()); | 215 FixedArray* elements = FixedArray::cast(copy->elements()); |
| 214 if (elements->map() == heap->fixed_cow_array_map()) { | 216 if (elements->map() == heap->fixed_cow_array_map()) { |
| 215 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 217 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
| 216 #ifdef DEBUG | 218 #ifdef DEBUG |
| 217 for (int i = 0; i < elements->length(); i++) { | 219 for (int i = 0; i < elements->length(); i++) { |
| 218 ASSERT(!elements->get(i)->IsJSObject()); | 220 ASSERT(!elements->get(i)->IsJSObject()); |
| 219 } | 221 } |
| 220 #endif | 222 #endif |
| 221 } else { | 223 } else { |
| 222 for (int i = 0; i < elements->length(); i++) { | 224 for (int i = 0; i < elements->length(); i++) { |
| 223 Object* value = elements->get(i); | 225 Object* value = elements->get(i); |
| 224 ASSERT(value->IsSmi() || | 226 ASSERT(value->IsSmi() || |
| 225 value->IsTheHole() || | 227 value->IsTheHole() || |
| 226 (copy->GetElementsKind() == FAST_ELEMENTS)); | 228 (IsFastObjectElementsKind(copy->GetElementsKind()))); |
| 227 if (value->IsJSObject()) { | 229 if (value->IsJSObject()) { |
| 228 JSObject* js_object = JSObject::cast(value); | 230 JSObject* js_object = JSObject::cast(value); |
| 229 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, | 231 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, |
| 230 js_object); | 232 js_object); |
| 231 if (!maybe_result->ToObject(&result)) return maybe_result; | 233 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 232 } | 234 } |
| 233 elements->set(i, result); | 235 elements->set(i, result); |
| 234 } | 236 } |
| 235 } | 237 } |
| 236 } | 238 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 261 case EXTERNAL_PIXEL_ELEMENTS: | 263 case EXTERNAL_PIXEL_ELEMENTS: |
| 262 case EXTERNAL_BYTE_ELEMENTS: | 264 case EXTERNAL_BYTE_ELEMENTS: |
| 263 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 265 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 264 case EXTERNAL_SHORT_ELEMENTS: | 266 case EXTERNAL_SHORT_ELEMENTS: |
| 265 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 267 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 266 case EXTERNAL_INT_ELEMENTS: | 268 case EXTERNAL_INT_ELEMENTS: |
| 267 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 269 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 268 case EXTERNAL_FLOAT_ELEMENTS: | 270 case EXTERNAL_FLOAT_ELEMENTS: |
| 269 case EXTERNAL_DOUBLE_ELEMENTS: | 271 case EXTERNAL_DOUBLE_ELEMENTS: |
| 270 case FAST_DOUBLE_ELEMENTS: | 272 case FAST_DOUBLE_ELEMENTS: |
| 273 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 271 // No contained objects, nothing to do. | 274 // No contained objects, nothing to do. |
| 272 break; | 275 break; |
| 273 } | 276 } |
| 274 return copy; | 277 return copy; |
| 275 } | 278 } |
| 276 | 279 |
| 277 | 280 |
| 278 static Handle<Map> ComputeObjectLiteralMap( | 281 static Handle<Map> ComputeObjectLiteralMap( |
| 279 Handle<Context> context, | 282 Handle<Context> context, |
| 280 Handle<FixedArray> constant_properties, | 283 Handle<FixedArray> constant_properties, |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 if (Map::IsValidElementsTransition(from_kind, to_kind)) { | 448 if (Map::IsValidElementsTransition(from_kind, to_kind)) { |
| 446 Handle<Object> result = JSObject::TransitionElementsKind( | 449 Handle<Object> result = JSObject::TransitionElementsKind( |
| 447 Handle<JSObject>::cast(object), to_kind); | 450 Handle<JSObject>::cast(object), to_kind); |
| 448 if (result.is_null()) return isolate->ThrowIllegalOperation(); | 451 if (result.is_null()) return isolate->ThrowIllegalOperation(); |
| 449 return *result; | 452 return *result; |
| 450 } | 453 } |
| 451 return isolate->ThrowIllegalOperation(); | 454 return isolate->ThrowIllegalOperation(); |
| 452 } | 455 } |
| 453 | 456 |
| 454 | 457 |
| 455 static const int kSmiOnlyLiteralMinimumLength = 1024; | 458 static const int kSmiLiteralMinimumLength = 1024; |
| 456 | 459 |
| 457 | 460 |
| 458 Handle<Object> Runtime::CreateArrayLiteralBoilerplate( | 461 Handle<Object> Runtime::CreateArrayLiteralBoilerplate( |
| 459 Isolate* isolate, | 462 Isolate* isolate, |
| 460 Handle<FixedArray> literals, | 463 Handle<FixedArray> literals, |
| 461 Handle<FixedArray> elements) { | 464 Handle<FixedArray> elements) { |
| 462 // Create the JSArray. | 465 // Create the JSArray. |
| 463 Handle<JSFunction> constructor( | 466 Handle<JSFunction> constructor( |
| 464 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); | 467 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); |
| 465 Handle<JSArray> object = | 468 Handle<JSArray> object = |
| 466 Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor)); | 469 Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor)); |
| 467 | 470 |
| 468 ElementsKind constant_elements_kind = | 471 ElementsKind constant_elements_kind = |
| 469 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); | 472 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); |
| 470 Handle<FixedArrayBase> constant_elements_values( | 473 Handle<FixedArrayBase> constant_elements_values( |
| 471 FixedArrayBase::cast(elements->get(1))); | 474 FixedArrayBase::cast(elements->get(1))); |
| 472 | 475 |
| 476 ASSERT(IsFastElementsKind(constant_elements_kind)); |
| 473 Context* global_context = isolate->context()->global_context(); | 477 Context* global_context = isolate->context()->global_context(); |
| 474 if (constant_elements_kind == FAST_SMI_ONLY_ELEMENTS) { | 478 Object* maybe_maps_array = global_context->js_array_maps(); |
| 475 object->set_map(Map::cast(global_context->smi_js_array_map())); | 479 ASSERT(!maybe_maps_array->IsUndefined()); |
| 476 } else if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) { | 480 Object* maybe_map = FixedArray::cast(maybe_maps_array)->get( |
| 477 object->set_map(Map::cast(global_context->double_js_array_map())); | 481 constant_elements_kind); |
| 478 } else { | 482 ASSERT(maybe_map->IsMap()); |
| 479 object->set_map(Map::cast(global_context->object_js_array_map())); | 483 object->set_map(Map::cast(maybe_map)); |
| 480 } | |
| 481 | 484 |
| 482 Handle<FixedArrayBase> copied_elements_values; | 485 Handle<FixedArrayBase> copied_elements_values; |
| 483 if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) { | 486 if (IsFastDoubleElementsKind(constant_elements_kind)) { |
| 484 ASSERT(FLAG_smi_only_arrays); | 487 ASSERT(FLAG_smi_only_arrays); |
| 485 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( | 488 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( |
| 486 Handle<FixedDoubleArray>::cast(constant_elements_values)); | 489 Handle<FixedDoubleArray>::cast(constant_elements_values)); |
| 487 } else { | 490 } else { |
| 488 ASSERT(constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || | 491 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind)); |
| 489 constant_elements_kind == FAST_ELEMENTS); | |
| 490 const bool is_cow = | 492 const bool is_cow = |
| 491 (constant_elements_values->map() == | 493 (constant_elements_values->map() == |
| 492 isolate->heap()->fixed_cow_array_map()); | 494 isolate->heap()->fixed_cow_array_map()); |
| 493 if (is_cow) { | 495 if (is_cow) { |
| 494 copied_elements_values = constant_elements_values; | 496 copied_elements_values = constant_elements_values; |
| 495 #if DEBUG | 497 #if DEBUG |
| 496 Handle<FixedArray> fixed_array_values = | 498 Handle<FixedArray> fixed_array_values = |
| 497 Handle<FixedArray>::cast(copied_elements_values); | 499 Handle<FixedArray>::cast(copied_elements_values); |
| 498 for (int i = 0; i < fixed_array_values->length(); i++) { | 500 for (int i = 0; i < fixed_array_values->length(); i++) { |
| 499 ASSERT(!fixed_array_values->get(i)->IsFixedArray()); | 501 ASSERT(!fixed_array_values->get(i)->IsFixedArray()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 515 CreateLiteralBoilerplate(isolate, literals, fa); | 517 CreateLiteralBoilerplate(isolate, literals, fa); |
| 516 if (result.is_null()) return result; | 518 if (result.is_null()) return result; |
| 517 fixed_array_values_copy->set(i, *result); | 519 fixed_array_values_copy->set(i, *result); |
| 518 } | 520 } |
| 519 } | 521 } |
| 520 } | 522 } |
| 521 } | 523 } |
| 522 object->set_elements(*copied_elements_values); | 524 object->set_elements(*copied_elements_values); |
| 523 object->set_length(Smi::FromInt(copied_elements_values->length())); | 525 object->set_length(Smi::FromInt(copied_elements_values->length())); |
| 524 | 526 |
| 525 // Ensure that the boilerplate object has FAST_ELEMENTS, unless the flag is | 527 // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is |
| 526 // on or the object is larger than the threshold. | 528 // on or the object is larger than the threshold. |
| 527 if (!FLAG_smi_only_arrays && | 529 if (!FLAG_smi_only_arrays && |
| 528 constant_elements_values->length() < kSmiOnlyLiteralMinimumLength) { | 530 constant_elements_values->length() < kSmiLiteralMinimumLength) { |
| 529 if (object->GetElementsKind() != FAST_ELEMENTS) { | 531 ElementsKind elements_kind = object->GetElementsKind(); |
| 530 CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure()); | 532 if (!IsFastObjectElementsKind(elements_kind)) { |
| 533 if (IsFastHoleyElementsKind(elements_kind)) { |
| 534 CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS, |
| 535 isolate)->IsFailure()); |
| 536 } else { |
| 537 CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure()); |
| 538 } |
| 531 } | 539 } |
| 532 } | 540 } |
| 533 | 541 |
| 534 return object; | 542 return object; |
| 535 } | 543 } |
| 536 | 544 |
| 537 | 545 |
| 538 static Handle<Object> CreateLiteralBoilerplate( | 546 static Handle<Object> CreateLiteralBoilerplate( |
| 539 Isolate* isolate, | 547 Isolate* isolate, |
| 540 Handle<FixedArray> literals, | 548 Handle<FixedArray> literals, |
| (...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 | 1731 |
| 1724 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { | 1732 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { |
| 1725 HandleScope scope(isolate); | 1733 HandleScope scope(isolate); |
| 1726 ASSERT(args.length() == 4); | 1734 ASSERT(args.length() == 4); |
| 1727 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); | 1735 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); |
| 1728 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); | 1736 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); |
| 1729 // Due to the way the JS calls are constructed this must be less than the | 1737 // Due to the way the JS calls are constructed this must be less than the |
| 1730 // length of a string, i.e. it is always a Smi. We check anyway for security. | 1738 // length of a string, i.e. it is always a Smi. We check anyway for security. |
| 1731 CONVERT_SMI_ARG_CHECKED(index, 2); | 1739 CONVERT_SMI_ARG_CHECKED(index, 2); |
| 1732 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3); | 1740 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3); |
| 1733 RUNTIME_ASSERT(last_match_info->HasFastElements()); | 1741 RUNTIME_ASSERT(last_match_info->HasFastObjectElements()); |
| 1734 RUNTIME_ASSERT(index >= 0); | 1742 RUNTIME_ASSERT(index >= 0); |
| 1735 RUNTIME_ASSERT(index <= subject->length()); | 1743 RUNTIME_ASSERT(index <= subject->length()); |
| 1736 isolate->counters()->regexp_entry_runtime()->Increment(); | 1744 isolate->counters()->regexp_entry_runtime()->Increment(); |
| 1737 Handle<Object> result = RegExpImpl::Exec(regexp, | 1745 Handle<Object> result = RegExpImpl::Exec(regexp, |
| 1738 subject, | 1746 subject, |
| 1739 index, | 1747 index, |
| 1740 last_match_info); | 1748 last_match_info); |
| 1741 if (result.is_null()) return Failure::Exception(); | 1749 if (result.is_null()) return Failure::Exception(); |
| 1742 return *result; | 1750 return *result; |
| 1743 } | 1751 } |
| (...skipping 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3097 | 3105 |
| 3098 // Index of end of last match. | 3106 // Index of end of last match. |
| 3099 int prev = 0; | 3107 int prev = 0; |
| 3100 | 3108 |
| 3101 // Number of parts added by compiled replacement plus preceeding | 3109 // Number of parts added by compiled replacement plus preceeding |
| 3102 // string and possibly suffix after last match. It is possible for | 3110 // string and possibly suffix after last match. It is possible for |
| 3103 // all components to use two elements when encoded as two smis. | 3111 // all components to use two elements when encoded as two smis. |
| 3104 const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2); | 3112 const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2); |
| 3105 bool matched = true; | 3113 bool matched = true; |
| 3106 do { | 3114 do { |
| 3107 ASSERT(last_match_info_handle->HasFastElements()); | 3115 ASSERT(last_match_info_handle->HasFastObjectElements()); |
| 3108 // Increase the capacity of the builder before entering local handle-scope, | 3116 // Increase the capacity of the builder before entering local handle-scope, |
| 3109 // so its internal buffer can safely allocate a new handle if it grows. | 3117 // so its internal buffer can safely allocate a new handle if it grows. |
| 3110 builder.EnsureCapacity(parts_added_per_loop); | 3118 builder.EnsureCapacity(parts_added_per_loop); |
| 3111 | 3119 |
| 3112 HandleScope loop_scope(isolate); | 3120 HandleScope loop_scope(isolate); |
| 3113 int start, end; | 3121 int start, end; |
| 3114 { | 3122 { |
| 3115 AssertNoAllocation match_info_array_is_not_in_a_handle; | 3123 AssertNoAllocation match_info_array_is_not_in_a_handle; |
| 3116 FixedArray* match_info_array = | 3124 FixedArray* match_info_array = |
| 3117 FixedArray::cast(last_match_info_handle->elements()); | 3125 FixedArray::cast(last_match_info_handle->elements()); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3194 } | 3202 } |
| 3195 } | 3203 } |
| 3196 | 3204 |
| 3197 Handle<Object> match = RegExpImpl::Exec(regexp_handle, | 3205 Handle<Object> match = RegExpImpl::Exec(regexp_handle, |
| 3198 subject_handle, | 3206 subject_handle, |
| 3199 0, | 3207 0, |
| 3200 last_match_info_handle); | 3208 last_match_info_handle); |
| 3201 if (match.is_null()) return Failure::Exception(); | 3209 if (match.is_null()) return Failure::Exception(); |
| 3202 if (match->IsNull()) return *subject_handle; | 3210 if (match->IsNull()) return *subject_handle; |
| 3203 | 3211 |
| 3204 ASSERT(last_match_info_handle->HasFastElements()); | 3212 ASSERT(last_match_info_handle->HasFastObjectElements()); |
| 3205 | 3213 |
| 3206 int start, end; | 3214 int start, end; |
| 3207 { | 3215 { |
| 3208 AssertNoAllocation match_info_array_is_not_in_a_handle; | 3216 AssertNoAllocation match_info_array_is_not_in_a_handle; |
| 3209 FixedArray* match_info_array = | 3217 FixedArray* match_info_array = |
| 3210 FixedArray::cast(last_match_info_handle->elements()); | 3218 FixedArray::cast(last_match_info_handle->elements()); |
| 3211 | 3219 |
| 3212 start = RegExpImpl::GetCapture(match_info_array, 0); | 3220 start = RegExpImpl::GetCapture(match_info_array, 0); |
| 3213 end = RegExpImpl::GetCapture(match_info_array, 1); | 3221 end = RegExpImpl::GetCapture(match_info_array, 1); |
| 3214 } | 3222 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3268 next++; | 3276 next++; |
| 3269 if (next > length) break; | 3277 if (next > length) break; |
| 3270 } | 3278 } |
| 3271 match = RegExpImpl::Exec(regexp_handle, | 3279 match = RegExpImpl::Exec(regexp_handle, |
| 3272 subject_handle, | 3280 subject_handle, |
| 3273 next, | 3281 next, |
| 3274 last_match_info_handle); | 3282 last_match_info_handle); |
| 3275 if (match.is_null()) return Failure::Exception(); | 3283 if (match.is_null()) return Failure::Exception(); |
| 3276 if (match->IsNull()) break; | 3284 if (match->IsNull()) break; |
| 3277 | 3285 |
| 3278 ASSERT(last_match_info_handle->HasFastElements()); | 3286 ASSERT(last_match_info_handle->HasFastObjectElements()); |
| 3279 HandleScope loop_scope(isolate); | 3287 HandleScope loop_scope(isolate); |
| 3280 { | 3288 { |
| 3281 AssertNoAllocation match_info_array_is_not_in_a_handle; | 3289 AssertNoAllocation match_info_array_is_not_in_a_handle; |
| 3282 FixedArray* match_info_array = | 3290 FixedArray* match_info_array = |
| 3283 FixedArray::cast(last_match_info_handle->elements()); | 3291 FixedArray::cast(last_match_info_handle->elements()); |
| 3284 start = RegExpImpl::GetCapture(match_info_array, 0); | 3292 start = RegExpImpl::GetCapture(match_info_array, 0); |
| 3285 end = RegExpImpl::GetCapture(match_info_array, 1); | 3293 end = RegExpImpl::GetCapture(match_info_array, 1); |
| 3286 } | 3294 } |
| 3287 } while (true); | 3295 } while (true); |
| 3288 | 3296 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3338 if (!maybe_flat_replacement->ToObject(&flat_replacement)) { | 3346 if (!maybe_flat_replacement->ToObject(&flat_replacement)) { |
| 3339 return maybe_flat_replacement; | 3347 return maybe_flat_replacement; |
| 3340 } | 3348 } |
| 3341 } | 3349 } |
| 3342 replacement = String::cast(flat_replacement); | 3350 replacement = String::cast(flat_replacement); |
| 3343 } | 3351 } |
| 3344 | 3352 |
| 3345 CONVERT_ARG_CHECKED(JSRegExp, regexp, 1); | 3353 CONVERT_ARG_CHECKED(JSRegExp, regexp, 1); |
| 3346 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); | 3354 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); |
| 3347 | 3355 |
| 3348 ASSERT(last_match_info->HasFastElements()); | 3356 ASSERT(last_match_info->HasFastObjectElements()); |
| 3349 | 3357 |
| 3350 if (replacement->length() == 0) { | 3358 if (replacement->length() == 0) { |
| 3351 if (subject->HasOnlyAsciiChars()) { | 3359 if (subject->HasOnlyAsciiChars()) { |
| 3352 return StringReplaceRegExpWithEmptyString<SeqAsciiString>( | 3360 return StringReplaceRegExpWithEmptyString<SeqAsciiString>( |
| 3353 isolate, subject, regexp, last_match_info); | 3361 isolate, subject, regexp, last_match_info); |
| 3354 } else { | 3362 } else { |
| 3355 return StringReplaceRegExpWithEmptyString<SeqTwoByteString>( | 3363 return StringReplaceRegExpWithEmptyString<SeqTwoByteString>( |
| 3356 isolate, subject, regexp, last_match_info); | 3364 isolate, subject, regexp, last_match_info); |
| 3357 } | 3365 } |
| 3358 } | 3366 } |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4003 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { | 4011 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { |
| 4004 ASSERT(args.length() == 4); | 4012 ASSERT(args.length() == 4); |
| 4005 HandleScope handles(isolate); | 4013 HandleScope handles(isolate); |
| 4006 | 4014 |
| 4007 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); | 4015 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); |
| 4008 if (!subject->IsFlat()) FlattenString(subject); | 4016 if (!subject->IsFlat()) FlattenString(subject); |
| 4009 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); | 4017 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); |
| 4010 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2); | 4018 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2); |
| 4011 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); | 4019 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); |
| 4012 | 4020 |
| 4013 ASSERT(last_match_info->HasFastElements()); | 4021 ASSERT(last_match_info->HasFastObjectElements()); |
| 4014 ASSERT(regexp->GetFlags().is_global()); | 4022 ASSERT(regexp->GetFlags().is_global()); |
| 4015 Handle<FixedArray> result_elements; | 4023 Handle<FixedArray> result_elements; |
| 4016 if (result_array->HasFastElements()) { | 4024 if (result_array->HasFastObjectElements()) { |
| 4017 result_elements = | 4025 result_elements = |
| 4018 Handle<FixedArray>(FixedArray::cast(result_array->elements())); | 4026 Handle<FixedArray>(FixedArray::cast(result_array->elements())); |
| 4019 } | 4027 } |
| 4020 if (result_elements.is_null() || result_elements->length() < 16) { | 4028 if (result_elements.is_null() || result_elements->length() < 16) { |
| 4021 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); | 4029 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); |
| 4022 } | 4030 } |
| 4023 FixedArrayBuilder builder(result_elements); | 4031 FixedArrayBuilder builder(result_elements); |
| 4024 | 4032 |
| 4025 if (regexp->TypeTag() == JSRegExp::ATOM) { | 4033 if (regexp->TypeTag() == JSRegExp::ATOM) { |
| 4026 Handle<String> pattern( | 4034 Handle<String> pattern( |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4308 if (!receiver->IsGlobalObject()) return value; | 4316 if (!receiver->IsGlobalObject()) return value; |
| 4309 value = JSGlobalPropertyCell::cast(value)->value(); | 4317 value = JSGlobalPropertyCell::cast(value)->value(); |
| 4310 if (!value->IsTheHole()) return value; | 4318 if (!value->IsTheHole()) return value; |
| 4311 // If value is the hole do the general lookup. | 4319 // If value is the hole do the general lookup. |
| 4312 } | 4320 } |
| 4313 } | 4321 } |
| 4314 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) { | 4322 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) { |
| 4315 // JSObject without a string key. If the key is a Smi, check for a | 4323 // JSObject without a string key. If the key is a Smi, check for a |
| 4316 // definite out-of-bounds access to elements, which is a strong indicator | 4324 // definite out-of-bounds access to elements, which is a strong indicator |
| 4317 // that subsequent accesses will also call the runtime. Proactively | 4325 // that subsequent accesses will also call the runtime. Proactively |
| 4318 // transition elements to FAST_ELEMENTS to avoid excessive boxing of | 4326 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of |
| 4319 // doubles for those future calls in the case that the elements would | 4327 // doubles for those future calls in the case that the elements would |
| 4320 // become FAST_DOUBLE_ELEMENTS. | 4328 // become FAST_DOUBLE_ELEMENTS. |
| 4321 Handle<JSObject> js_object(args.at<JSObject>(0)); | 4329 Handle<JSObject> js_object(args.at<JSObject>(0)); |
| 4322 ElementsKind elements_kind = js_object->GetElementsKind(); | 4330 ElementsKind elements_kind = js_object->GetElementsKind(); |
| 4323 if (elements_kind == FAST_SMI_ONLY_ELEMENTS || | 4331 if (IsFastSmiElementsKind(elements_kind)) { |
| 4324 elements_kind == FAST_DOUBLE_ELEMENTS) { | |
| 4325 FixedArrayBase* elements = js_object->elements(); | 4332 FixedArrayBase* elements = js_object->elements(); |
| 4326 if (args.at<Smi>(1)->value() >= elements->length()) { | 4333 if (args.at<Smi>(1)->value() >= elements->length()) { |
| 4334 elements_kind = FastSmiToObjectElementsKind(elements_kind); |
| 4327 MaybeObject* maybe_object = TransitionElements(js_object, | 4335 MaybeObject* maybe_object = TransitionElements(js_object, |
| 4328 FAST_ELEMENTS, | 4336 elements_kind, |
| 4329 isolate); | 4337 isolate); |
| 4330 if (maybe_object->IsFailure()) return maybe_object; | 4338 if (maybe_object->IsFailure()) return maybe_object; |
| 4331 } | 4339 } |
| 4332 } | 4340 } |
| 4333 } | 4341 } |
| 4334 } else if (args[0]->IsString() && args[1]->IsSmi()) { | 4342 } else if (args[0]->IsString() && args[1]->IsSmi()) { |
| 4335 // Fast case for string indexing using [] with a smi index. | 4343 // Fast case for string indexing using [] with a smi index. |
| 4336 HandleScope scope(isolate); | 4344 HandleScope scope(isolate); |
| 4337 Handle<String> str = args.at<String>(0); | 4345 Handle<String> str = args.at<String>(0); |
| 4338 int index = args.smi_at(1); | 4346 int index = args.smi_at(1); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4488 // of a string using [] notation. We need to support this too in | 4496 // of a string using [] notation. We need to support this too in |
| 4489 // JavaScript. | 4497 // JavaScript. |
| 4490 // In the case of a String object we just need to redirect the assignment to | 4498 // In the case of a String object we just need to redirect the assignment to |
| 4491 // the underlying string if the index is in range. Since the underlying | 4499 // the underlying string if the index is in range. Since the underlying |
| 4492 // string does nothing with the assignment then we can ignore such | 4500 // string does nothing with the assignment then we can ignore such |
| 4493 // assignments. | 4501 // assignments. |
| 4494 if (js_object->IsStringObjectWithCharacterAt(index)) { | 4502 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 4495 return *value; | 4503 return *value; |
| 4496 } | 4504 } |
| 4497 | 4505 |
| 4506 #if DEBUG |
| 4507 js_object->ValidateElements(); |
| 4508 #endif |
| 4498 Handle<Object> result = JSObject::SetElement( | 4509 Handle<Object> result = JSObject::SetElement( |
| 4499 js_object, index, value, attr, strict_mode, set_mode); | 4510 js_object, index, value, attr, strict_mode, set_mode); |
| 4511 #if DEBUG |
| 4512 js_object->ValidateElements(); |
| 4513 #endif |
| 4500 if (result.is_null()) return Failure::Exception(); | 4514 if (result.is_null()) return Failure::Exception(); |
| 4501 return *value; | 4515 return *value; |
| 4502 } | 4516 } |
| 4503 | 4517 |
| 4504 if (key->IsString()) { | 4518 if (key->IsString()) { |
| 4505 Handle<Object> result; | 4519 Handle<Object> result; |
| 4506 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 4520 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 4507 result = JSObject::SetElement( | 4521 result = JSObject::SetElement( |
| 4508 js_object, index, value, attr, strict_mode, set_mode); | 4522 js_object, index, value, attr, strict_mode, set_mode); |
| 4509 } else { | 4523 } else { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4647 value, | 4661 value, |
| 4648 attributes, | 4662 attributes, |
| 4649 strict_mode); | 4663 strict_mode); |
| 4650 } | 4664 } |
| 4651 | 4665 |
| 4652 | 4666 |
| 4653 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) { | 4667 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) { |
| 4654 NoHandleAllocation ha; | 4668 NoHandleAllocation ha; |
| 4655 RUNTIME_ASSERT(args.length() == 1); | 4669 RUNTIME_ASSERT(args.length() == 1); |
| 4656 Handle<Object> object = args.at<Object>(0); | 4670 Handle<Object> object = args.at<Object>(0); |
| 4657 return TransitionElements(object, FAST_DOUBLE_ELEMENTS, isolate); | 4671 if (object->IsJSObject()) { |
| 4672 Handle<JSObject> js_object(Handle<JSObject>::cast(object)); |
| 4673 ElementsKind new_kind = js_object->HasFastHoleyElements() |
| 4674 ? FAST_HOLEY_DOUBLE_ELEMENTS |
| 4675 : FAST_DOUBLE_ELEMENTS; |
| 4676 return TransitionElements(object, new_kind, isolate); |
| 4677 } else { |
| 4678 return *object; |
| 4679 } |
| 4658 } | 4680 } |
| 4659 | 4681 |
| 4660 | 4682 |
| 4661 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) { | 4683 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) { |
| 4662 NoHandleAllocation ha; | 4684 NoHandleAllocation ha; |
| 4663 RUNTIME_ASSERT(args.length() == 1); | 4685 RUNTIME_ASSERT(args.length() == 1); |
| 4664 Handle<Object> object = args.at<Object>(0); | 4686 Handle<Object> object = args.at<Object>(0); |
| 4665 return TransitionElements(object, FAST_ELEMENTS, isolate); | 4687 if (object->IsJSObject()) { |
| 4688 Handle<JSObject> js_object(Handle<JSObject>::cast(object)); |
| 4689 ElementsKind new_kind = js_object->HasFastHoleyElements() |
| 4690 ? FAST_HOLEY_ELEMENTS |
| 4691 : FAST_ELEMENTS; |
| 4692 return TransitionElements(object, new_kind, isolate); |
| 4693 } else { |
| 4694 return *object; |
| 4695 } |
| 4666 } | 4696 } |
| 4667 | 4697 |
| 4668 | 4698 |
| 4669 // Set the native flag on the function. | 4699 // Set the native flag on the function. |
| 4670 // This is used to decide if we should transform null and undefined | 4700 // This is used to decide if we should transform null and undefined |
| 4671 // into the global object when doing call and apply. | 4701 // into the global object when doing call and apply. |
| 4672 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) { | 4702 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) { |
| 4673 NoHandleAllocation ha; | 4703 NoHandleAllocation ha; |
| 4674 RUNTIME_ASSERT(args.length() == 1); | 4704 RUNTIME_ASSERT(args.length() == 1); |
| 4675 | 4705 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4686 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) { | 4716 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) { |
| 4687 RUNTIME_ASSERT(args.length() == 5); | 4717 RUNTIME_ASSERT(args.length() == 5); |
| 4688 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 4718 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 4689 CONVERT_SMI_ARG_CHECKED(store_index, 1); | 4719 CONVERT_SMI_ARG_CHECKED(store_index, 1); |
| 4690 Handle<Object> value = args.at<Object>(2); | 4720 Handle<Object> value = args.at<Object>(2); |
| 4691 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3); | 4721 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3); |
| 4692 CONVERT_SMI_ARG_CHECKED(literal_index, 4); | 4722 CONVERT_SMI_ARG_CHECKED(literal_index, 4); |
| 4693 HandleScope scope; | 4723 HandleScope scope; |
| 4694 | 4724 |
| 4695 Object* raw_boilerplate_object = literals->get(literal_index); | 4725 Object* raw_boilerplate_object = literals->get(literal_index); |
| 4696 Handle<JSArray> boilerplate(JSArray::cast(raw_boilerplate_object)); | 4726 Handle<JSArray> boilerplate_object(JSArray::cast(raw_boilerplate_object)); |
| 4697 #if DEBUG | |
| 4698 ElementsKind elements_kind = object->GetElementsKind(); | 4727 ElementsKind elements_kind = object->GetElementsKind(); |
| 4699 #endif | 4728 ASSERT(IsFastElementsKind(elements_kind)); |
| 4700 ASSERT(elements_kind <= FAST_DOUBLE_ELEMENTS); | |
| 4701 // Smis should never trigger transitions. | 4729 // Smis should never trigger transitions. |
| 4702 ASSERT(!value->IsSmi()); | 4730 ASSERT(!value->IsSmi()); |
| 4703 | 4731 |
| 4704 if (value->IsNumber()) { | 4732 if (value->IsNumber()) { |
| 4705 ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS); | 4733 ASSERT(IsFastSmiElementsKind(elements_kind)); |
| 4706 JSObject::TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); | 4734 ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind) |
| 4707 if (IsMoreGeneralElementsKindTransition(boilerplate->GetElementsKind(), | 4735 ? FAST_HOLEY_DOUBLE_ELEMENTS |
| 4708 FAST_DOUBLE_ELEMENTS)) { | 4736 : FAST_DOUBLE_ELEMENTS; |
| 4709 JSObject::TransitionElementsKind(boilerplate, FAST_DOUBLE_ELEMENTS); | 4737 if (IsMoreGeneralElementsKindTransition( |
| 4738 boilerplate_object->GetElementsKind(), |
| 4739 transitioned_kind)) { |
| 4740 JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind); |
| 4710 } | 4741 } |
| 4711 ASSERT(object->GetElementsKind() == FAST_DOUBLE_ELEMENTS); | 4742 JSObject::TransitionElementsKind(object, transitioned_kind); |
| 4712 FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements()); | 4743 ASSERT(IsFastDoubleElementsKind(object->GetElementsKind())); |
| 4744 FixedDoubleArray* double_array = |
| 4745 FixedDoubleArray::cast(object->elements()); |
| 4713 HeapNumber* number = HeapNumber::cast(*value); | 4746 HeapNumber* number = HeapNumber::cast(*value); |
| 4714 double_array->set(store_index, number->Number()); | 4747 double_array->set(store_index, number->Number()); |
| 4715 } else { | 4748 } else { |
| 4716 ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS || | 4749 ASSERT(IsFastSmiElementsKind(elements_kind) || |
| 4717 elements_kind == FAST_DOUBLE_ELEMENTS); | 4750 IsFastDoubleElementsKind(elements_kind)); |
| 4718 JSObject::TransitionElementsKind(object, FAST_ELEMENTS); | 4751 ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind) |
| 4719 if (IsMoreGeneralElementsKindTransition(boilerplate->GetElementsKind(), | 4752 ? FAST_HOLEY_ELEMENTS |
| 4720 FAST_ELEMENTS)) { | 4753 : FAST_ELEMENTS; |
| 4721 JSObject::TransitionElementsKind(boilerplate, FAST_ELEMENTS); | 4754 JSObject::TransitionElementsKind(object, transitioned_kind); |
| 4755 if (IsMoreGeneralElementsKindTransition( |
| 4756 boilerplate_object->GetElementsKind(), |
| 4757 transitioned_kind)) { |
| 4758 JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind); |
| 4722 } | 4759 } |
| 4723 FixedArray* object_array = FixedArray::cast(object->elements()); | 4760 FixedArray* object_array = |
| 4761 FixedArray::cast(object->elements()); |
| 4724 object_array->set(store_index, *value); | 4762 object_array->set(store_index, *value); |
| 4725 } | 4763 } |
| 4726 return *object; | 4764 return *object; |
| 4727 } | 4765 } |
| 4728 | 4766 |
| 4729 | 4767 |
| 4730 // Check whether debugger and is about to step into the callback that is passed | 4768 // Check whether debugger and is about to step into the callback that is passed |
| 4731 // to a built-in function such as Array.forEach. | 4769 // to a built-in function such as Array.forEach. |
| 4732 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) { | 4770 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) { |
| 4733 if (!isolate->IsDebuggerActive()) return isolate->heap()->false_value(); | 4771 if (!isolate->IsDebuggerActive()) return isolate->heap()->false_value(); |
| (...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5924 new_string, final_length); | 5962 new_string, final_length); |
| 5925 return new_string; | 5963 return new_string; |
| 5926 } | 5964 } |
| 5927 | 5965 |
| 5928 | 5966 |
| 5929 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { | 5967 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { |
| 5930 NoHandleAllocation ha; | 5968 NoHandleAllocation ha; |
| 5931 ASSERT(args.length() == 1); | 5969 ASSERT(args.length() == 1); |
| 5932 CONVERT_ARG_CHECKED(JSArray, array, 0); | 5970 CONVERT_ARG_CHECKED(JSArray, array, 0); |
| 5933 | 5971 |
| 5934 if (!array->HasFastElements()) return isolate->heap()->undefined_value(); | 5972 if (!array->HasFastObjectElements()) { |
| 5973 return isolate->heap()->undefined_value(); |
| 5974 } |
| 5935 FixedArray* elements = FixedArray::cast(array->elements()); | 5975 FixedArray* elements = FixedArray::cast(array->elements()); |
| 5936 int n = elements->length(); | 5976 int n = elements->length(); |
| 5937 bool ascii = true; | 5977 bool ascii = true; |
| 5938 int total_length = 0; | 5978 int total_length = 0; |
| 5939 | 5979 |
| 5940 for (int i = 0; i < n; i++) { | 5980 for (int i = 0; i < n; i++) { |
| 5941 Object* elt = elements->get(i); | 5981 Object* elt = elements->get(i); |
| 5942 if (!elt->IsString()) return isolate->heap()->undefined_value(); | 5982 if (!elt->IsString()) return isolate->heap()->undefined_value(); |
| 5943 String* element = String::cast(elt); | 5983 String* element = String::cast(elt); |
| 5944 if (!element->IsFlat()) return isolate->heap()->undefined_value(); | 5984 if (!element->IsFlat()) return isolate->heap()->undefined_value(); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6367 // The list indices now contains the end of each part to create. | 6407 // The list indices now contains the end of each part to create. |
| 6368 | 6408 |
| 6369 // Create JSArray of substrings separated by separator. | 6409 // Create JSArray of substrings separated by separator. |
| 6370 int part_count = indices.length(); | 6410 int part_count = indices.length(); |
| 6371 | 6411 |
| 6372 Handle<JSArray> result = isolate->factory()->NewJSArray(part_count); | 6412 Handle<JSArray> result = isolate->factory()->NewJSArray(part_count); |
| 6373 MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements(); | 6413 MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements(); |
| 6374 if (maybe_result->IsFailure()) return maybe_result; | 6414 if (maybe_result->IsFailure()) return maybe_result; |
| 6375 result->set_length(Smi::FromInt(part_count)); | 6415 result->set_length(Smi::FromInt(part_count)); |
| 6376 | 6416 |
| 6377 ASSERT(result->HasFastElements()); | 6417 ASSERT(result->HasFastObjectElements()); |
| 6378 | 6418 |
| 6379 if (part_count == 1 && indices.at(0) == subject_length) { | 6419 if (part_count == 1 && indices.at(0) == subject_length) { |
| 6380 FixedArray::cast(result->elements())->set(0, *subject); | 6420 FixedArray::cast(result->elements())->set(0, *subject); |
| 6381 return *result; | 6421 return *result; |
| 6382 } | 6422 } |
| 6383 | 6423 |
| 6384 Handle<FixedArray> elements(FixedArray::cast(result->elements())); | 6424 Handle<FixedArray> elements(FixedArray::cast(result->elements())); |
| 6385 int part_start = 0; | 6425 int part_start = 0; |
| 6386 for (int i = 0; i < part_count; i++) { | 6426 for (int i = 0; i < part_count; i++) { |
| 6387 HandleScope local_loop_handle; | 6427 HandleScope local_loop_handle; |
| 6388 int part_end = indices.at(i); | 6428 int part_end = indices.at(i); |
| 6389 Handle<String> substring = | 6429 Handle<String> substring = |
| 6390 isolate->factory()->NewProperSubString(subject, part_start, part_end); | 6430 isolate->factory()->NewProperSubString(subject, part_start, part_end); |
| 6391 elements->set(i, *substring); | 6431 elements->set(i, *substring); |
| 6392 part_start = part_end + pattern_length; | 6432 part_start = part_end + pattern_length; |
| 6393 } | 6433 } |
| 6394 | 6434 |
| 6395 if (limit == 0xffffffffu) { | 6435 if (limit == 0xffffffffu) { |
| 6396 if (result->HasFastElements()) { | 6436 if (result->HasFastObjectElements()) { |
| 6397 StringSplitCache::Enter(isolate->heap(), | 6437 StringSplitCache::Enter(isolate->heap(), |
| 6398 isolate->heap()->string_split_cache(), | 6438 isolate->heap()->string_split_cache(), |
| 6399 *subject, | 6439 *subject, |
| 6400 *pattern, | 6440 *pattern, |
| 6401 *elements); | 6441 *elements); |
| 6402 } | 6442 } |
| 6403 } | 6443 } |
| 6404 | 6444 |
| 6405 return *result; | 6445 return *result; |
| 6406 } | 6446 } |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6743 int array_length = args.smi_at(1); | 6783 int array_length = args.smi_at(1); |
| 6744 CONVERT_ARG_CHECKED(String, special, 2); | 6784 CONVERT_ARG_CHECKED(String, special, 2); |
| 6745 | 6785 |
| 6746 // This assumption is used by the slice encoding in one or two smis. | 6786 // This assumption is used by the slice encoding in one or two smis. |
| 6747 ASSERT(Smi::kMaxValue >= String::kMaxLength); | 6787 ASSERT(Smi::kMaxValue >= String::kMaxLength); |
| 6748 | 6788 |
| 6749 MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements(); | 6789 MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements(); |
| 6750 if (maybe_result->IsFailure()) return maybe_result; | 6790 if (maybe_result->IsFailure()) return maybe_result; |
| 6751 | 6791 |
| 6752 int special_length = special->length(); | 6792 int special_length = special->length(); |
| 6753 if (!array->HasFastElements()) { | 6793 if (!array->HasFastObjectElements()) { |
| 6754 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); | 6794 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); |
| 6755 } | 6795 } |
| 6756 FixedArray* fixed_array = FixedArray::cast(array->elements()); | 6796 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
| 6757 if (fixed_array->length() < array_length) { | 6797 if (fixed_array->length() < array_length) { |
| 6758 array_length = fixed_array->length(); | 6798 array_length = fixed_array->length(); |
| 6759 } | 6799 } |
| 6760 | 6800 |
| 6761 if (array_length == 0) { | 6801 if (array_length == 0) { |
| 6762 return isolate->heap()->empty_string(); | 6802 return isolate->heap()->empty_string(); |
| 6763 } else if (array_length == 1) { | 6803 } else if (array_length == 1) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6853 NoHandleAllocation ha; | 6893 NoHandleAllocation ha; |
| 6854 ASSERT(args.length() == 3); | 6894 ASSERT(args.length() == 3); |
| 6855 CONVERT_ARG_CHECKED(JSArray, array, 0); | 6895 CONVERT_ARG_CHECKED(JSArray, array, 0); |
| 6856 if (!args[1]->IsSmi()) { | 6896 if (!args[1]->IsSmi()) { |
| 6857 isolate->context()->mark_out_of_memory(); | 6897 isolate->context()->mark_out_of_memory(); |
| 6858 return Failure::OutOfMemoryException(); | 6898 return Failure::OutOfMemoryException(); |
| 6859 } | 6899 } |
| 6860 int array_length = args.smi_at(1); | 6900 int array_length = args.smi_at(1); |
| 6861 CONVERT_ARG_CHECKED(String, separator, 2); | 6901 CONVERT_ARG_CHECKED(String, separator, 2); |
| 6862 | 6902 |
| 6863 if (!array->HasFastElements()) { | 6903 if (!array->HasFastObjectElements()) { |
| 6864 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); | 6904 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); |
| 6865 } | 6905 } |
| 6866 FixedArray* fixed_array = FixedArray::cast(array->elements()); | 6906 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
| 6867 if (fixed_array->length() < array_length) { | 6907 if (fixed_array->length() < array_length) { |
| 6868 array_length = fixed_array->length(); | 6908 array_length = fixed_array->length(); |
| 6869 } | 6909 } |
| 6870 | 6910 |
| 6871 if (array_length == 0) { | 6911 if (array_length == 0) { |
| 6872 return isolate->heap()->empty_string(); | 6912 return isolate->heap()->empty_string(); |
| 6873 } else if (array_length == 1) { | 6913 } else if (array_length == 1) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6970 } | 7010 } |
| 6971 } | 7011 } |
| 6972 ASSERT(cursor <= buffer.length()); | 7012 ASSERT(cursor <= buffer.length()); |
| 6973 } | 7013 } |
| 6974 | 7014 |
| 6975 | 7015 |
| 6976 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { | 7016 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { |
| 6977 NoHandleAllocation ha; | 7017 NoHandleAllocation ha; |
| 6978 ASSERT(args.length() == 3); | 7018 ASSERT(args.length() == 3); |
| 6979 CONVERT_ARG_CHECKED(JSArray, elements_array, 0); | 7019 CONVERT_ARG_CHECKED(JSArray, elements_array, 0); |
| 6980 RUNTIME_ASSERT(elements_array->HasFastElements() || | 7020 RUNTIME_ASSERT(elements_array->HasFastObjectElements() || |
| 6981 elements_array->HasFastSmiOnlyElements()); | 7021 elements_array->HasFastSmiElements()); |
| 6982 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); | 7022 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); |
| 6983 CONVERT_ARG_CHECKED(String, separator, 2); | 7023 CONVERT_ARG_CHECKED(String, separator, 2); |
| 6984 // elements_array is fast-mode JSarray of alternating positions | 7024 // elements_array is fast-mode JSarray of alternating positions |
| 6985 // (increasing order) and strings. | 7025 // (increasing order) and strings. |
| 6986 // array_length is length of original array (used to add separators); | 7026 // array_length is length of original array (used to add separators); |
| 6987 // separator is string to put between elements. Assumed to be non-empty. | 7027 // separator is string to put between elements. Assumed to be non-empty. |
| 6988 | 7028 |
| 6989 // Find total length of join result. | 7029 // Find total length of join result. |
| 6990 int string_length = 0; | 7030 int string_length = 0; |
| 6991 bool is_ascii = separator->IsAsciiRepresentation(); | 7031 bool is_ascii = separator->IsAsciiRepresentation(); |
| (...skipping 2124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9116 ASSERT(args.length() == 2); | 9156 ASSERT(args.length() == 2); |
| 9117 | 9157 |
| 9118 CONVERT_ARG_HANDLE_CHECKED(String, str, 0); | 9158 CONVERT_ARG_HANDLE_CHECKED(String, str, 0); |
| 9119 FlattenString(str); | 9159 FlattenString(str); |
| 9120 | 9160 |
| 9121 CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1); | 9161 CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1); |
| 9122 | 9162 |
| 9123 MaybeObject* maybe_result_array = | 9163 MaybeObject* maybe_result_array = |
| 9124 output->EnsureCanContainHeapObjectElements(); | 9164 output->EnsureCanContainHeapObjectElements(); |
| 9125 if (maybe_result_array->IsFailure()) return maybe_result_array; | 9165 if (maybe_result_array->IsFailure()) return maybe_result_array; |
| 9126 RUNTIME_ASSERT(output->HasFastElements()); | 9166 RUNTIME_ASSERT(output->HasFastObjectElements()); |
| 9127 | 9167 |
| 9128 AssertNoAllocation no_allocation; | 9168 AssertNoAllocation no_allocation; |
| 9129 | 9169 |
| 9130 FixedArray* output_array = FixedArray::cast(output->elements()); | 9170 FixedArray* output_array = FixedArray::cast(output->elements()); |
| 9131 RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); | 9171 RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE); |
| 9132 bool result; | 9172 bool result; |
| 9133 String::FlatContent str_content = str->GetFlatContent(); | 9173 String::FlatContent str_content = str->GetFlatContent(); |
| 9134 if (str_content.IsAscii()) { | 9174 if (str_content.IsAscii()) { |
| 9135 result = DateParser::Parse(str_content.ToAsciiVector(), | 9175 result = DateParser::Parse(str_content.ToAsciiVector(), |
| 9136 output_array, | 9176 output_array, |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9348 } | 9388 } |
| 9349 | 9389 |
| 9350 | 9390 |
| 9351 // Push an object unto an array of objects if it is not already in the | 9391 // Push an object unto an array of objects if it is not already in the |
| 9352 // array. Returns true if the element was pushed on the stack and | 9392 // array. Returns true if the element was pushed on the stack and |
| 9353 // false otherwise. | 9393 // false otherwise. |
| 9354 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { | 9394 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { |
| 9355 ASSERT(args.length() == 2); | 9395 ASSERT(args.length() == 2); |
| 9356 CONVERT_ARG_CHECKED(JSArray, array, 0); | 9396 CONVERT_ARG_CHECKED(JSArray, array, 0); |
| 9357 CONVERT_ARG_CHECKED(JSObject, element, 1); | 9397 CONVERT_ARG_CHECKED(JSObject, element, 1); |
| 9358 RUNTIME_ASSERT(array->HasFastElements() || array->HasFastSmiOnlyElements()); | 9398 RUNTIME_ASSERT(array->HasFastSmiOrObjectElements()); |
| 9359 int length = Smi::cast(array->length())->value(); | 9399 int length = Smi::cast(array->length())->value(); |
| 9360 FixedArray* elements = FixedArray::cast(array->elements()); | 9400 FixedArray* elements = FixedArray::cast(array->elements()); |
| 9361 for (int i = 0; i < length; i++) { | 9401 for (int i = 0; i < length; i++) { |
| 9362 if (elements->get(i) == element) return isolate->heap()->false_value(); | 9402 if (elements->get(i) == element) return isolate->heap()->false_value(); |
| 9363 } | 9403 } |
| 9364 Object* obj; | 9404 Object* obj; |
| 9365 // Strict not needed. Used for cycle detection in Array join implementation. | 9405 // Strict not needed. Used for cycle detection in Array join implementation. |
| 9366 { MaybeObject* maybe_obj = | 9406 { MaybeObject* maybe_obj = |
| 9367 array->SetFastElement(length, element, kNonStrictMode, true); | 9407 array->SetFastElement(length, element, kNonStrictMode, true); |
| 9368 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9408 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9433 } | 9473 } |
| 9434 } | 9474 } |
| 9435 | 9475 |
| 9436 Handle<JSArray> ToArray() { | 9476 Handle<JSArray> ToArray() { |
| 9437 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); | 9477 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); |
| 9438 Handle<Object> length = | 9478 Handle<Object> length = |
| 9439 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); | 9479 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); |
| 9440 Handle<Map> map; | 9480 Handle<Map> map; |
| 9441 if (fast_elements_) { | 9481 if (fast_elements_) { |
| 9442 map = isolate_->factory()->GetElementsTransitionMap(array, | 9482 map = isolate_->factory()->GetElementsTransitionMap(array, |
| 9443 FAST_ELEMENTS); | 9483 FAST_HOLEY_ELEMENTS); |
| 9444 } else { | 9484 } else { |
| 9445 map = isolate_->factory()->GetElementsTransitionMap(array, | 9485 map = isolate_->factory()->GetElementsTransitionMap(array, |
| 9446 DICTIONARY_ELEMENTS); | 9486 DICTIONARY_ELEMENTS); |
| 9447 } | 9487 } |
| 9448 array->set_map(*map); | 9488 array->set_map(*map); |
| 9449 array->set_length(*length); | 9489 array->set_length(*length); |
| 9450 array->set_elements(*storage_); | 9490 array->set_elements(*storage_); |
| 9451 return array; | 9491 return array; |
| 9452 } | 9492 } |
| 9453 | 9493 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9492 // JSObject::kMaxElementCount. | 9532 // JSObject::kMaxElementCount. |
| 9493 uint32_t index_offset_; | 9533 uint32_t index_offset_; |
| 9494 bool fast_elements_; | 9534 bool fast_elements_; |
| 9495 }; | 9535 }; |
| 9496 | 9536 |
| 9497 | 9537 |
| 9498 static uint32_t EstimateElementCount(Handle<JSArray> array) { | 9538 static uint32_t EstimateElementCount(Handle<JSArray> array) { |
| 9499 uint32_t length = static_cast<uint32_t>(array->length()->Number()); | 9539 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
| 9500 int element_count = 0; | 9540 int element_count = 0; |
| 9501 switch (array->GetElementsKind()) { | 9541 switch (array->GetElementsKind()) { |
| 9502 case FAST_SMI_ONLY_ELEMENTS: | 9542 case FAST_SMI_ELEMENTS: |
| 9503 case FAST_ELEMENTS: { | 9543 case FAST_HOLEY_SMI_ELEMENTS: |
| 9544 case FAST_ELEMENTS: |
| 9545 case FAST_HOLEY_ELEMENTS: { |
| 9504 // Fast elements can't have lengths that are not representable by | 9546 // Fast elements can't have lengths that are not representable by |
| 9505 // a 32-bit signed integer. | 9547 // a 32-bit signed integer. |
| 9506 ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0); | 9548 ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0); |
| 9507 int fast_length = static_cast<int>(length); | 9549 int fast_length = static_cast<int>(length); |
| 9508 Handle<FixedArray> elements(FixedArray::cast(array->elements())); | 9550 Handle<FixedArray> elements(FixedArray::cast(array->elements())); |
| 9509 for (int i = 0; i < fast_length; i++) { | 9551 for (int i = 0; i < fast_length; i++) { |
| 9510 if (!elements->get(i)->IsTheHole()) element_count++; | 9552 if (!elements->get(i)->IsTheHole()) element_count++; |
| 9511 } | 9553 } |
| 9512 break; | 9554 break; |
| 9513 } | 9555 } |
| 9514 case FAST_DOUBLE_ELEMENTS: | 9556 case FAST_DOUBLE_ELEMENTS: |
| 9557 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 9515 // TODO(1810): Decide if it's worthwhile to implement this. | 9558 // TODO(1810): Decide if it's worthwhile to implement this. |
| 9516 UNREACHABLE(); | 9559 UNREACHABLE(); |
| 9517 break; | 9560 break; |
| 9518 case DICTIONARY_ELEMENTS: { | 9561 case DICTIONARY_ELEMENTS: { |
| 9519 Handle<SeededNumberDictionary> dictionary( | 9562 Handle<SeededNumberDictionary> dictionary( |
| 9520 SeededNumberDictionary::cast(array->elements())); | 9563 SeededNumberDictionary::cast(array->elements())); |
| 9521 int capacity = dictionary->Capacity(); | 9564 int capacity = dictionary->Capacity(); |
| 9522 for (int i = 0; i < capacity; i++) { | 9565 for (int i = 0; i < capacity; i++) { |
| 9523 Handle<Object> key(dictionary->KeyAt(i)); | 9566 Handle<Object> key(dictionary->KeyAt(i)); |
| 9524 if (dictionary->IsKey(*key)) { | 9567 if (dictionary->IsKey(*key)) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9595 uint32_t b = *bp; | 9638 uint32_t b = *bp; |
| 9596 return (a == b) ? 0 : (a < b) ? -1 : 1; | 9639 return (a == b) ? 0 : (a < b) ? -1 : 1; |
| 9597 } | 9640 } |
| 9598 | 9641 |
| 9599 | 9642 |
| 9600 static void CollectElementIndices(Handle<JSObject> object, | 9643 static void CollectElementIndices(Handle<JSObject> object, |
| 9601 uint32_t range, | 9644 uint32_t range, |
| 9602 List<uint32_t>* indices) { | 9645 List<uint32_t>* indices) { |
| 9603 ElementsKind kind = object->GetElementsKind(); | 9646 ElementsKind kind = object->GetElementsKind(); |
| 9604 switch (kind) { | 9647 switch (kind) { |
| 9605 case FAST_SMI_ONLY_ELEMENTS: | 9648 case FAST_SMI_ELEMENTS: |
| 9606 case FAST_ELEMENTS: { | 9649 case FAST_ELEMENTS: |
| 9650 case FAST_HOLEY_SMI_ELEMENTS: |
| 9651 case FAST_HOLEY_ELEMENTS: { |
| 9607 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | 9652 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
| 9608 uint32_t length = static_cast<uint32_t>(elements->length()); | 9653 uint32_t length = static_cast<uint32_t>(elements->length()); |
| 9609 if (range < length) length = range; | 9654 if (range < length) length = range; |
| 9610 for (uint32_t i = 0; i < length; i++) { | 9655 for (uint32_t i = 0; i < length; i++) { |
| 9611 if (!elements->get(i)->IsTheHole()) { | 9656 if (!elements->get(i)->IsTheHole()) { |
| 9612 indices->Add(i); | 9657 indices->Add(i); |
| 9613 } | 9658 } |
| 9614 } | 9659 } |
| 9615 break; | 9660 break; |
| 9616 } | 9661 } |
| 9662 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 9617 case FAST_DOUBLE_ELEMENTS: { | 9663 case FAST_DOUBLE_ELEMENTS: { |
| 9618 // TODO(1810): Decide if it's worthwhile to implement this. | 9664 // TODO(1810): Decide if it's worthwhile to implement this. |
| 9619 UNREACHABLE(); | 9665 UNREACHABLE(); |
| 9620 break; | 9666 break; |
| 9621 } | 9667 } |
| 9622 case DICTIONARY_ELEMENTS: { | 9668 case DICTIONARY_ELEMENTS: { |
| 9623 Handle<SeededNumberDictionary> dict( | 9669 Handle<SeededNumberDictionary> dict( |
| 9624 SeededNumberDictionary::cast(object->elements())); | 9670 SeededNumberDictionary::cast(object->elements())); |
| 9625 uint32_t capacity = dict->Capacity(); | 9671 uint32_t capacity = dict->Capacity(); |
| 9626 for (uint32_t j = 0; j < capacity; j++) { | 9672 for (uint32_t j = 0; j < capacity; j++) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9721 * with the element index and the element's value. | 9767 * with the element index and the element's value. |
| 9722 * Afterwards it increments the base-index of the visitor by the array | 9768 * Afterwards it increments the base-index of the visitor by the array |
| 9723 * length. | 9769 * length. |
| 9724 * Returns false if any access threw an exception, otherwise true. | 9770 * Returns false if any access threw an exception, otherwise true. |
| 9725 */ | 9771 */ |
| 9726 static bool IterateElements(Isolate* isolate, | 9772 static bool IterateElements(Isolate* isolate, |
| 9727 Handle<JSArray> receiver, | 9773 Handle<JSArray> receiver, |
| 9728 ArrayConcatVisitor* visitor) { | 9774 ArrayConcatVisitor* visitor) { |
| 9729 uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); | 9775 uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); |
| 9730 switch (receiver->GetElementsKind()) { | 9776 switch (receiver->GetElementsKind()) { |
| 9731 case FAST_SMI_ONLY_ELEMENTS: | 9777 case FAST_SMI_ELEMENTS: |
| 9732 case FAST_ELEMENTS: { | 9778 case FAST_ELEMENTS: |
| 9779 case FAST_HOLEY_SMI_ELEMENTS: |
| 9780 case FAST_HOLEY_ELEMENTS: { |
| 9733 // Run through the elements FixedArray and use HasElement and GetElement | 9781 // Run through the elements FixedArray and use HasElement and GetElement |
| 9734 // to check the prototype for missing elements. | 9782 // to check the prototype for missing elements. |
| 9735 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); | 9783 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); |
| 9736 int fast_length = static_cast<int>(length); | 9784 int fast_length = static_cast<int>(length); |
| 9737 ASSERT(fast_length <= elements->length()); | 9785 ASSERT(fast_length <= elements->length()); |
| 9738 for (int j = 0; j < fast_length; j++) { | 9786 for (int j = 0; j < fast_length; j++) { |
| 9739 HandleScope loop_scope(isolate); | 9787 HandleScope loop_scope(isolate); |
| 9740 Handle<Object> element_value(elements->get(j), isolate); | 9788 Handle<Object> element_value(elements->get(j), isolate); |
| 9741 if (!element_value->IsTheHole()) { | 9789 if (!element_value->IsTheHole()) { |
| 9742 visitor->visit(j, element_value); | 9790 visitor->visit(j, element_value); |
| 9743 } else if (receiver->HasElement(j)) { | 9791 } else if (receiver->HasElement(j)) { |
| 9744 // Call GetElement on receiver, not its prototype, or getters won't | 9792 // Call GetElement on receiver, not its prototype, or getters won't |
| 9745 // have the correct receiver. | 9793 // have the correct receiver. |
| 9746 element_value = Object::GetElement(receiver, j); | 9794 element_value = Object::GetElement(receiver, j); |
| 9747 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false); | 9795 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false); |
| 9748 visitor->visit(j, element_value); | 9796 visitor->visit(j, element_value); |
| 9749 } | 9797 } |
| 9750 } | 9798 } |
| 9751 break; | 9799 break; |
| 9752 } | 9800 } |
| 9801 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 9753 case FAST_DOUBLE_ELEMENTS: { | 9802 case FAST_DOUBLE_ELEMENTS: { |
| 9754 // TODO(1810): Decide if it's worthwhile to implement this. | 9803 // TODO(1810): Decide if it's worthwhile to implement this. |
| 9755 UNREACHABLE(); | 9804 UNREACHABLE(); |
| 9756 break; | 9805 break; |
| 9757 } | 9806 } |
| 9758 case DICTIONARY_ELEMENTS: { | 9807 case DICTIONARY_ELEMENTS: { |
| 9759 Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); | 9808 Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); |
| 9760 List<uint32_t> indices(dict->Capacity() / 2); | 9809 List<uint32_t> indices(dict->Capacity() / 2); |
| 9761 // Collect all indices in the object and the prototypes less | 9810 // Collect all indices in the object and the prototypes less |
| 9762 // than length. This might introduce duplicates in the indices list. | 9811 // than length. This might introduce duplicates in the indices list. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9840 * See ECMAScript 262, 15.4.4.4. | 9889 * See ECMAScript 262, 15.4.4.4. |
| 9841 * TODO(581): Fix non-compliance for very large concatenations and update to | 9890 * TODO(581): Fix non-compliance for very large concatenations and update to |
| 9842 * following the ECMAScript 5 specification. | 9891 * following the ECMAScript 5 specification. |
| 9843 */ | 9892 */ |
| 9844 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { | 9893 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { |
| 9845 ASSERT(args.length() == 1); | 9894 ASSERT(args.length() == 1); |
| 9846 HandleScope handle_scope(isolate); | 9895 HandleScope handle_scope(isolate); |
| 9847 | 9896 |
| 9848 CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0); | 9897 CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0); |
| 9849 int argument_count = static_cast<int>(arguments->length()->Number()); | 9898 int argument_count = static_cast<int>(arguments->length()->Number()); |
| 9850 RUNTIME_ASSERT(arguments->HasFastElements()); | 9899 RUNTIME_ASSERT(arguments->HasFastObjectElements()); |
| 9851 Handle<FixedArray> elements(FixedArray::cast(arguments->elements())); | 9900 Handle<FixedArray> elements(FixedArray::cast(arguments->elements())); |
| 9852 | 9901 |
| 9853 // Pass 1: estimate the length and number of elements of the result. | 9902 // Pass 1: estimate the length and number of elements of the result. |
| 9854 // The actual length can be larger if any of the arguments have getters | 9903 // The actual length can be larger if any of the arguments have getters |
| 9855 // that mutate other arguments (but will otherwise be precise). | 9904 // that mutate other arguments (but will otherwise be precise). |
| 9856 // The number of elements is precise if there are no inherited elements. | 9905 // The number of elements is precise if there are no inherited elements. |
| 9857 | 9906 |
| 9858 uint32_t estimate_result_length = 0; | 9907 uint32_t estimate_result_length = 0; |
| 9859 uint32_t estimate_nof_elements = 0; | 9908 uint32_t estimate_nof_elements = 0; |
| 9860 { | 9909 { |
| 9861 for (int i = 0; i < argument_count; i++) { | 9910 for (int i = 0; i < argument_count; i++) { |
| 9862 HandleScope loop_scope; | 9911 HandleScope loop_scope; |
| 9863 Handle<Object> obj(elements->get(i)); | 9912 Handle<Object> obj(elements->get(i)); |
| 9864 uint32_t length_estimate; | 9913 uint32_t length_estimate; |
| 9865 uint32_t element_estimate; | 9914 uint32_t element_estimate; |
| 9866 if (obj->IsJSArray()) { | 9915 if (obj->IsJSArray()) { |
| 9867 Handle<JSArray> array(Handle<JSArray>::cast(obj)); | 9916 Handle<JSArray> array(Handle<JSArray>::cast(obj)); |
| 9868 // TODO(1810): Find out if it's worthwhile to properly support | 9917 // TODO(1810): Find out if it's worthwhile to properly support |
| 9869 // arbitrary ElementsKinds. For now, pessimistically transition to | 9918 // arbitrary ElementsKinds. For now, pessimistically transition to |
| 9870 // FAST_ELEMENTS. | 9919 // FAST_*_ELEMENTS. |
| 9871 if (array->HasFastDoubleElements()) { | 9920 if (array->HasFastDoubleElements()) { |
| 9921 ElementsKind to_kind = FAST_ELEMENTS; |
| 9922 if (array->HasFastHoleyElements()) { |
| 9923 to_kind = FAST_HOLEY_ELEMENTS; |
| 9924 } |
| 9872 array = Handle<JSArray>::cast( | 9925 array = Handle<JSArray>::cast( |
| 9873 JSObject::TransitionElementsKind(array, FAST_ELEMENTS)); | 9926 JSObject::TransitionElementsKind(array, FAST_ELEMENTS)); |
| 9874 } | 9927 } |
| 9875 length_estimate = | 9928 length_estimate = |
| 9876 static_cast<uint32_t>(array->length()->Number()); | 9929 static_cast<uint32_t>(array->length()->Number()); |
| 9877 element_estimate = | 9930 element_estimate = |
| 9878 EstimateElementCount(array); | 9931 EstimateElementCount(array); |
| 9879 } else { | 9932 } else { |
| 9880 length_estimate = 1; | 9933 length_estimate = 1; |
| 9881 element_estimate = 1; | 9934 element_estimate = 1; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9960 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]); | 10013 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]); |
| 9961 return object->PrepareElementsForSort(limit); | 10014 return object->PrepareElementsForSort(limit); |
| 9962 } | 10015 } |
| 9963 | 10016 |
| 9964 | 10017 |
| 9965 // Move contents of argument 0 (an array) to argument 1 (an array) | 10018 // Move contents of argument 0 (an array) to argument 1 (an array) |
| 9966 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) { | 10019 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) { |
| 9967 ASSERT(args.length() == 2); | 10020 ASSERT(args.length() == 2); |
| 9968 CONVERT_ARG_CHECKED(JSArray, from, 0); | 10021 CONVERT_ARG_CHECKED(JSArray, from, 0); |
| 9969 CONVERT_ARG_CHECKED(JSArray, to, 1); | 10022 CONVERT_ARG_CHECKED(JSArray, to, 1); |
| 10023 #if DEBUG |
| 10024 from->ValidateElements(); |
| 10025 to->ValidateElements(); |
| 10026 #endif |
| 9970 FixedArrayBase* new_elements = from->elements(); | 10027 FixedArrayBase* new_elements = from->elements(); |
| 10028 ElementsKind from_kind = from->GetElementsKind(); |
| 9971 MaybeObject* maybe_new_map; | 10029 MaybeObject* maybe_new_map; |
| 9972 ElementsKind elements_kind; | 10030 maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind); |
| 9973 if (new_elements->map() == isolate->heap()->fixed_array_map() || | |
| 9974 new_elements->map() == isolate->heap()->fixed_cow_array_map()) { | |
| 9975 elements_kind = FAST_ELEMENTS; | |
| 9976 } else if (new_elements->map() == | |
| 9977 isolate->heap()->fixed_double_array_map()) { | |
| 9978 elements_kind = FAST_DOUBLE_ELEMENTS; | |
| 9979 } else { | |
| 9980 elements_kind = DICTIONARY_ELEMENTS; | |
| 9981 } | |
| 9982 maybe_new_map = to->GetElementsTransitionMap(isolate, elements_kind); | |
| 9983 Object* new_map; | 10031 Object* new_map; |
| 9984 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 10032 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 9985 to->set_map(Map::cast(new_map)); | 10033 to->set_map_and_elements(Map::cast(new_map), new_elements); |
| 9986 to->set_elements(new_elements); | |
| 9987 to->set_length(from->length()); | 10034 to->set_length(from->length()); |
| 9988 Object* obj; | 10035 Object* obj; |
| 9989 { MaybeObject* maybe_obj = from->ResetElements(); | 10036 { MaybeObject* maybe_obj = from->ResetElements(); |
| 9990 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10037 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9991 } | 10038 } |
| 9992 from->set_length(Smi::FromInt(0)); | 10039 from->set_length(Smi::FromInt(0)); |
| 10040 #if DEBUG |
| 10041 to->ValidateElements(); |
| 10042 #endif |
| 9993 return to; | 10043 return to; |
| 9994 } | 10044 } |
| 9995 | 10045 |
| 9996 | 10046 |
| 9997 // How many elements does this object/array have? | 10047 // How many elements does this object/array have? |
| 9998 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) { | 10048 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) { |
| 9999 ASSERT(args.length() == 1); | 10049 ASSERT(args.length() == 1); |
| 10000 CONVERT_ARG_CHECKED(JSObject, object, 0); | 10050 CONVERT_ARG_CHECKED(JSObject, object, 0); |
| 10001 HeapObject* elements = object->elements(); | 10051 HeapObject* elements = object->elements(); |
| 10002 if (elements->IsDictionary()) { | 10052 if (elements->IsDictionary()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10062 for (int i = 0; i < keys_length; i++) { | 10112 for (int i = 0; i < keys_length; i++) { |
| 10063 Object* key = keys->get(i); | 10113 Object* key = keys->get(i); |
| 10064 uint32_t index = 0; | 10114 uint32_t index = 0; |
| 10065 if (!key->ToArrayIndex(&index) || index >= length) { | 10115 if (!key->ToArrayIndex(&index) || index >= length) { |
| 10066 // Zap invalid keys. | 10116 // Zap invalid keys. |
| 10067 keys->set_undefined(i); | 10117 keys->set_undefined(i); |
| 10068 } | 10118 } |
| 10069 } | 10119 } |
| 10070 return *isolate->factory()->NewJSArrayWithElements(keys); | 10120 return *isolate->factory()->NewJSArrayWithElements(keys); |
| 10071 } else { | 10121 } else { |
| 10072 ASSERT(array->HasFastElements() || | 10122 ASSERT(array->HasFastSmiOrObjectElements() || |
| 10073 array->HasFastSmiOnlyElements() || | |
| 10074 array->HasFastDoubleElements()); | 10123 array->HasFastDoubleElements()); |
| 10075 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); | 10124 Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2); |
| 10076 // -1 means start of array. | 10125 // -1 means start of array. |
| 10077 single_interval->set(0, Smi::FromInt(-1)); | 10126 single_interval->set(0, Smi::FromInt(-1)); |
| 10078 FixedArrayBase* elements = FixedArrayBase::cast(array->elements()); | 10127 FixedArrayBase* elements = FixedArrayBase::cast(array->elements()); |
| 10079 uint32_t actual_length = | 10128 uint32_t actual_length = |
| 10080 static_cast<uint32_t>(elements->length()); | 10129 static_cast<uint32_t>(elements->length()); |
| 10081 uint32_t min_length = actual_length < length ? actual_length : length; | 10130 uint32_t min_length = actual_length < length ? actual_length : length; |
| 10082 Handle<Object> length_object = | 10131 Handle<Object> length_object = |
| 10083 isolate->factory()->NewNumber(static_cast<double>(min_length)); | 10132 isolate->factory()->NewNumber(static_cast<double>(min_length)); |
| (...skipping 3238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13322 return NULL; | 13371 return NULL; |
| 13323 } | 13372 } |
| 13324 | 13373 |
| 13325 | 13374 |
| 13326 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ | 13375 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ |
| 13327 RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \ | 13376 RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \ |
| 13328 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ | 13377 CONVERT_ARG_CHECKED(JSObject, obj, 0); \ |
| 13329 return isolate->heap()->ToBoolean(obj->Has##Name()); \ | 13378 return isolate->heap()->ToBoolean(obj->Has##Name()); \ |
| 13330 } | 13379 } |
| 13331 | 13380 |
| 13332 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOnlyElements) | 13381 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements) |
| 13333 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements) | 13382 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements) |
| 13383 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements) |
| 13334 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) | 13384 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) |
| 13385 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements) |
| 13335 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) | 13386 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) |
| 13336 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements) | 13387 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements) |
| 13337 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) | 13388 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) |
| 13338 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements) | 13389 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements) |
| 13339 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements) | 13390 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements) |
| 13340 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements) | 13391 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements) |
| 13341 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements) | 13392 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements) |
| 13342 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements) | 13393 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements) |
| 13343 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements) | 13394 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements) |
| 13344 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements) | 13395 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13433 // Handle last resort GC and make sure to allow future allocations | 13484 // Handle last resort GC and make sure to allow future allocations |
| 13434 // to grow the heap without causing GCs (if possible). | 13485 // to grow the heap without causing GCs (if possible). |
| 13435 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13486 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13436 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13487 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 13437 "Runtime::PerformGC"); | 13488 "Runtime::PerformGC"); |
| 13438 } | 13489 } |
| 13439 } | 13490 } |
| 13440 | 13491 |
| 13441 | 13492 |
| 13442 } } // namespace v8::internal | 13493 } } // namespace v8::internal |
| OLD | NEW |