| 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 7254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7265 ASSERT(!answer->IsOneByteRepresentation()); | 7265 ASSERT(!answer->IsOneByteRepresentation()); |
| 7266 return *answer; | 7266 return *answer; |
| 7267 } | 7267 } |
| 7268 | 7268 |
| 7269 template <typename Char> | 7269 template <typename Char> |
| 7270 static void JoinSparseArrayWithSeparator(FixedArray* elements, | 7270 static void JoinSparseArrayWithSeparator(FixedArray* elements, |
| 7271 int elements_length, | 7271 int elements_length, |
| 7272 uint32_t array_length, | 7272 uint32_t array_length, |
| 7273 String* separator, | 7273 String* separator, |
| 7274 Vector<Char> buffer) { | 7274 Vector<Char> buffer) { |
| 7275 DisallowHeapAllocation no_gc; |
| 7275 int previous_separator_position = 0; | 7276 int previous_separator_position = 0; |
| 7276 int separator_length = separator->length(); | 7277 int separator_length = separator->length(); |
| 7277 int cursor = 0; | 7278 int cursor = 0; |
| 7278 for (int i = 0; i < elements_length; i += 2) { | 7279 for (int i = 0; i < elements_length; i += 2) { |
| 7279 int position = NumberToInt32(elements->get(i)); | 7280 int position = NumberToInt32(elements->get(i)); |
| 7280 String* string = String::cast(elements->get(i + 1)); | 7281 String* string = String::cast(elements->get(i + 1)); |
| 7281 int string_length = string->length(); | 7282 int string_length = string->length(); |
| 7282 if (string->length() > 0) { | 7283 if (string->length() > 0) { |
| 7283 while (previous_separator_position < position) { | 7284 while (previous_separator_position < position) { |
| 7284 String::WriteToFlat<Char>(separator, &buffer[cursor], | 7285 String::WriteToFlat<Char>(separator, &buffer[cursor], |
| (...skipping 18 matching lines...) Expand all Loading... |
| 7303 previous_separator_position++; | 7304 previous_separator_position++; |
| 7304 } | 7305 } |
| 7305 } | 7306 } |
| 7306 ASSERT(cursor <= buffer.length()); | 7307 ASSERT(cursor <= buffer.length()); |
| 7307 } | 7308 } |
| 7308 | 7309 |
| 7309 | 7310 |
| 7310 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { | 7311 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { |
| 7311 HandleScope scope(isolate); | 7312 HandleScope scope(isolate); |
| 7312 ASSERT(args.length() == 3); | 7313 ASSERT(args.length() == 3); |
| 7313 CONVERT_ARG_CHECKED(JSArray, elements_array, 0); | 7314 CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0); |
| 7314 RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements()); | 7315 RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements()); |
| 7315 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); | 7316 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); |
| 7316 CONVERT_ARG_CHECKED(String, separator, 2); | 7317 CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); |
| 7317 // elements_array is fast-mode JSarray of alternating positions | 7318 // elements_array is fast-mode JSarray of alternating positions |
| 7318 // (increasing order) and strings. | 7319 // (increasing order) and strings. |
| 7319 // array_length is length of original array (used to add separators); | 7320 // array_length is length of original array (used to add separators); |
| 7320 // separator is string to put between elements. Assumed to be non-empty. | 7321 // separator is string to put between elements. Assumed to be non-empty. |
| 7321 | 7322 |
| 7322 // Find total length of join result. | 7323 // Find total length of join result. |
| 7323 int string_length = 0; | 7324 int string_length = 0; |
| 7324 bool is_ascii = separator->IsOneByteRepresentation(); | 7325 bool is_ascii = separator->IsOneByteRepresentation(); |
| 7325 bool overflow = false; | 7326 bool overflow = false; |
| 7326 CONVERT_NUMBER_CHECKED(int, elements_length, | 7327 CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length()); |
| 7327 Int32, elements_array->length()); | |
| 7328 RUNTIME_ASSERT((elements_length & 1) == 0); // Even length. | 7328 RUNTIME_ASSERT((elements_length & 1) == 0); // Even length. |
| 7329 FixedArray* elements = FixedArray::cast(elements_array->elements()); | 7329 |
| 7330 for (int i = 0; i < elements_length; i += 2) { | 7330 { DisallowHeapAllocation no_gc; |
| 7331 RUNTIME_ASSERT(elements->get(i)->IsNumber()); | 7331 FixedArray* elements = FixedArray::cast(elements_array->elements()); |
| 7332 RUNTIME_ASSERT(elements->get(i + 1)->IsString()); | 7332 for (int i = 0; i < elements_length; i += 2) { |
| 7333 String* string = String::cast(elements->get(i + 1)); | 7333 RUNTIME_ASSERT(elements->get(i)->IsNumber()); |
| 7334 int length = string->length(); | 7334 RUNTIME_ASSERT(elements->get(i + 1)->IsString()); |
| 7335 if (is_ascii && !string->IsOneByteRepresentation()) { | 7335 String* string = String::cast(elements->get(i + 1)); |
| 7336 is_ascii = false; | 7336 int length = string->length(); |
| 7337 if (is_ascii && !string->IsOneByteRepresentation()) { |
| 7338 is_ascii = false; |
| 7339 } |
| 7340 if (length > String::kMaxLength || |
| 7341 String::kMaxLength - length < string_length) { |
| 7342 overflow = true; |
| 7343 break; |
| 7344 } |
| 7345 string_length += length; |
| 7337 } | 7346 } |
| 7338 if (length > String::kMaxLength || | |
| 7339 String::kMaxLength - length < string_length) { | |
| 7340 overflow = true; | |
| 7341 break; | |
| 7342 } | |
| 7343 string_length += length; | |
| 7344 } | 7347 } |
| 7348 |
| 7345 int separator_length = separator->length(); | 7349 int separator_length = separator->length(); |
| 7346 if (!overflow && separator_length > 0) { | 7350 if (!overflow && separator_length > 0) { |
| 7347 if (array_length <= 0x7fffffffu) { | 7351 if (array_length <= 0x7fffffffu) { |
| 7348 int separator_count = static_cast<int>(array_length) - 1; | 7352 int separator_count = static_cast<int>(array_length) - 1; |
| 7349 int remaining_length = String::kMaxLength - string_length; | 7353 int remaining_length = String::kMaxLength - string_length; |
| 7350 if ((remaining_length / separator_length) >= separator_count) { | 7354 if ((remaining_length / separator_length) >= separator_count) { |
| 7351 string_length += separator_length * (array_length - 1); | 7355 string_length += separator_length * (array_length - 1); |
| 7352 } else { | 7356 } else { |
| 7353 // Not room for the separators within the maximal string length. | 7357 // Not room for the separators within the maximal string length. |
| 7354 overflow = true; | 7358 overflow = true; |
| 7355 } | 7359 } |
| 7356 } else { | 7360 } else { |
| 7357 // Nonempty separator and at least 2^31-1 separators necessary | 7361 // Nonempty separator and at least 2^31-1 separators necessary |
| 7358 // means that the string is too large to create. | 7362 // means that the string is too large to create. |
| 7359 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); | 7363 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); |
| 7360 overflow = true; | 7364 overflow = true; |
| 7361 } | 7365 } |
| 7362 } | 7366 } |
| 7363 if (overflow) { | 7367 if (overflow) { |
| 7364 // Throw an exception if the resulting string is too large. See | 7368 // Throw an exception if the resulting string is too large. See |
| 7365 // https://code.google.com/p/chromium/issues/detail?id=336820 | 7369 // https://code.google.com/p/chromium/issues/detail?id=336820 |
| 7366 // for details. | 7370 // for details. |
| 7367 return isolate->ThrowInvalidStringLength(); | 7371 return isolate->ThrowInvalidStringLength(); |
| 7368 } | 7372 } |
| 7369 | 7373 |
| 7370 if (is_ascii) { | 7374 if (is_ascii) { |
| 7371 MaybeObject* result_allocation = | 7375 Handle<SeqOneByteString> result = isolate->factory()->NewRawOneByteString( |
| 7372 isolate->heap()->AllocateRawOneByteString(string_length); | 7376 string_length).ToHandleChecked(); |
| 7373 if (result_allocation->IsFailure()) return result_allocation; | 7377 JoinSparseArrayWithSeparator<uint8_t>( |
| 7374 SeqOneByteString* result_string = | 7378 FixedArray::cast(elements_array->elements()), |
| 7375 SeqOneByteString::cast(result_allocation->ToObjectUnchecked()); | 7379 elements_length, |
| 7376 JoinSparseArrayWithSeparator<uint8_t>(elements, | 7380 array_length, |
| 7377 elements_length, | 7381 *separator, |
| 7378 array_length, | 7382 Vector<uint8_t>(result->GetChars(), string_length)); |
| 7379 separator, | 7383 return *result; |
| 7380 Vector<uint8_t>( | |
| 7381 result_string->GetChars(), | |
| 7382 string_length)); | |
| 7383 return result_string; | |
| 7384 } else { | 7384 } else { |
| 7385 MaybeObject* result_allocation = | 7385 Handle<SeqTwoByteString> result = isolate->factory()->NewRawTwoByteString( |
| 7386 isolate->heap()->AllocateRawTwoByteString(string_length); | 7386 string_length).ToHandleChecked(); |
| 7387 if (result_allocation->IsFailure()) return result_allocation; | 7387 JoinSparseArrayWithSeparator<uc16>( |
| 7388 SeqTwoByteString* result_string = | 7388 FixedArray::cast(elements_array->elements()), |
| 7389 SeqTwoByteString::cast(result_allocation->ToObjectUnchecked()); | 7389 elements_length, |
| 7390 JoinSparseArrayWithSeparator<uc16>(elements, | 7390 array_length, |
| 7391 elements_length, | 7391 *separator, |
| 7392 array_length, | 7392 Vector<uc16>(result->GetChars(), string_length)); |
| 7393 separator, | 7393 return *result; |
| 7394 Vector<uc16>(result_string->GetChars(), | |
| 7395 string_length)); | |
| 7396 return result_string; | |
| 7397 } | 7394 } |
| 7398 } | 7395 } |
| 7399 | 7396 |
| 7400 | 7397 |
| 7401 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) { | 7398 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) { |
| 7402 HandleScope scope(isolate); | 7399 HandleScope scope(isolate); |
| 7403 ASSERT(args.length() == 2); | 7400 ASSERT(args.length() == 2); |
| 7404 | 7401 |
| 7405 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | 7402 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); |
| 7406 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | 7403 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); |
| (...skipping 1757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9164 #elif defined(V8_TARGET_BIG_ENDIAN) | 9161 #elif defined(V8_TARGET_BIG_ENDIAN) |
| 9165 return reinterpret_cast<uint32_t>(y) | | 9162 return reinterpret_cast<uint32_t>(y) | |
| 9166 (reinterpret_cast<ObjectPair>(x) << 32); | 9163 (reinterpret_cast<ObjectPair>(x) << 32); |
| 9167 #else | 9164 #else |
| 9168 #error Unknown endianness | 9165 #error Unknown endianness |
| 9169 #endif | 9166 #endif |
| 9170 } | 9167 } |
| 9171 #endif | 9168 #endif |
| 9172 | 9169 |
| 9173 | 9170 |
| 9174 static inline MaybeObject* Unhole(Heap* heap, | |
| 9175 MaybeObject* x, | |
| 9176 PropertyAttributes attributes) { | |
| 9177 ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0); | |
| 9178 USE(attributes); | |
| 9179 return x->IsTheHole() ? heap->undefined_value() : x; | |
| 9180 } | |
| 9181 | |
| 9182 | |
| 9183 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, | 9171 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, |
| 9184 JSObject* holder) { | 9172 JSObject* holder) { |
| 9185 ASSERT(!holder->IsGlobalObject()); | 9173 ASSERT(!holder->IsGlobalObject()); |
| 9186 Context* top = isolate->context(); | 9174 Context* top = isolate->context(); |
| 9187 // Get the context extension function. | 9175 // Get the context extension function. |
| 9188 JSFunction* context_extension_function = | 9176 JSFunction* context_extension_function = |
| 9189 top->native_context()->context_extension_function(); | 9177 top->native_context()->context_extension_function(); |
| 9190 // If the holder isn't a context extension object, we just return it | 9178 // If the holder isn't a context extension object, we just return it |
| 9191 // as the receiver. This allows arguments objects to be used as | 9179 // as the receiver. This allows arguments objects to be used as |
| 9192 // receivers, but only if they are put in the context scope chain | 9180 // receivers, but only if they are put in the context scope chain |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9242 HandleVector(&name, 1)); | 9230 HandleVector(&name, 1)); |
| 9243 return MakePair(isolate->Throw(*reference_error), NULL); | 9231 return MakePair(isolate->Throw(*reference_error), NULL); |
| 9244 } | 9232 } |
| 9245 // FALLTHROUGH | 9233 // FALLTHROUGH |
| 9246 case MUTABLE_IS_INITIALIZED: | 9234 case MUTABLE_IS_INITIALIZED: |
| 9247 case IMMUTABLE_IS_INITIALIZED: | 9235 case IMMUTABLE_IS_INITIALIZED: |
| 9248 case IMMUTABLE_IS_INITIALIZED_HARMONY: | 9236 case IMMUTABLE_IS_INITIALIZED_HARMONY: |
| 9249 ASSERT(!value->IsTheHole()); | 9237 ASSERT(!value->IsTheHole()); |
| 9250 return MakePair(value, *receiver); | 9238 return MakePair(value, *receiver); |
| 9251 case IMMUTABLE_CHECK_INITIALIZED: | 9239 case IMMUTABLE_CHECK_INITIALIZED: |
| 9252 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); | 9240 if (value->IsTheHole()) { |
| 9241 ASSERT((attributes & READ_ONLY) != 0); |
| 9242 value = isolate->heap()->undefined_value(); |
| 9243 } |
| 9244 return MakePair(value, *receiver); |
| 9253 case MISSING_BINDING: | 9245 case MISSING_BINDING: |
| 9254 UNREACHABLE(); | 9246 UNREACHABLE(); |
| 9255 return MakePair(NULL, NULL); | 9247 return MakePair(NULL, NULL); |
| 9256 } | 9248 } |
| 9257 } | 9249 } |
| 9258 | 9250 |
| 9259 // Otherwise, if the slot was found the holder is a context extension | 9251 // Otherwise, if the slot was found the holder is a context extension |
| 9260 // object, subject of a with, or a global object. We read the named | 9252 // object, subject of a with, or a global object. We read the named |
| 9261 // property from it. | 9253 // property from it. |
| 9262 if (!holder.is_null()) { | 9254 if (!holder.is_null()) { |
| (...skipping 5829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15092 } | 15084 } |
| 15093 } | 15085 } |
| 15094 | 15086 |
| 15095 | 15087 |
| 15096 void Runtime::OutOfMemory() { | 15088 void Runtime::OutOfMemory() { |
| 15097 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); | 15089 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); |
| 15098 UNREACHABLE(); | 15090 UNREACHABLE(); |
| 15099 } | 15091 } |
| 15100 | 15092 |
| 15101 } } // namespace v8::internal | 15093 } } // namespace v8::internal |
| OLD | NEW |