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 |