Chromium Code Reviews| 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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 UNREACHABLE(); | 179 UNREACHABLE(); |
| 180 return isolate->heap()->undefined_value(); // Make compiler happy. | 180 return isolate->heap()->undefined_value(); // Make compiler happy. |
| 181 } | 181 } |
| 182 | 182 |
| 183 | 183 |
| 184 BUILTIN(EmptyFunction) { | 184 BUILTIN(EmptyFunction) { |
| 185 return isolate->heap()->undefined_value(); | 185 return isolate->heap()->undefined_value(); |
| 186 } | 186 } |
| 187 | 187 |
| 188 | 188 |
| 189 #define CONVERT_ARG_STUB_CALLER_ARGS(name) \ | |
| 190 Arguments* name = reinterpret_cast<Arguments*>(args[0]); | |
| 191 | |
| 192 | |
| 193 RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure) { | |
| 194 CONVERT_ARG_STUB_CALLER_ARGS(caller_args); | |
| 195 // ASSERT(args.length() == 3); | |
| 196 Handle<JSFunction> function = args.at<JSFunction>(1); | |
| 197 Handle<Object> type_info = args.at<Object>(2); | |
| 198 | |
| 199 JSArray* array = NULL; | |
| 200 bool holey = false; | |
| 201 if (caller_args->length() == 1 && (*caller_args)[0]->IsSmi()) { | |
| 202 int value = Smi::cast((*caller_args)[0])->value(); | |
| 203 holey = (value > 0 && value < JSObject::kInitialMaxFastElementArray); | |
| 204 } | |
| 205 | |
| 206 // Allocate the initial map if absent. | |
| 207 if (!function->has_initial_map()) { | |
| 208 Object* initial_map; | |
| 209 { MaybeObject* maybe_initial_map = | |
| 210 isolate->heap()->AllocateInitialMap(*function); | |
| 211 if (!maybe_initial_map->ToObject(&initial_map)) return maybe_initial_map; | |
| 212 } | |
|
Toon Verwaest
2013/02/13 15:14:51
Remove { ... }; replace ToObject(& by To(&; set th
mvstanton
2013/02/19 11:04:08
Indeed, it won't be called until after the initial
| |
| 213 function->set_initial_map(Map::cast(initial_map)); | |
| 214 Map::cast(initial_map)->set_constructor(*function); | |
| 215 } | |
| 216 | |
| 217 ElementsKind kind = function->initial_map()->elements_kind(); | |
| 218 if (holey) { | |
| 219 kind = GetHoleyElementsKind(kind); | |
| 220 } | |
| 221 | |
| 222 MaybeObject* maybe_array; | |
| 223 if (*type_info != isolate->heap()->undefined_value()) { | |
| 224 ASSERT(type_info->IsJSGlobalPropertyCell()); | |
| 225 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info); | |
| 226 if (cell->value()->IsSmi()) { | |
| 227 Smi* smi = Smi::cast(cell->value()); | |
| 228 ElementsKind to_kind = static_cast<ElementsKind>(smi->value()); | |
| 229 if (holey) { | |
|
Toon Verwaest
2013/02/13 15:14:51
If this is holey, you'll probably want to update t
mvstanton
2013/02/19 11:04:08
Done.
| |
| 230 to_kind = GetHoleyElementsKind(to_kind); | |
| 231 } | |
| 232 | |
| 233 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | |
|
Toon Verwaest
2013/02/13 15:14:51
Shouldn't happen I guess. Otherwise we are doing a
mvstanton
2013/02/19 11:04:08
good point, I'll let the ::GetMode(kind) call belo
| |
| 234 maybe_array = isolate->heap()->AllocateEmptyJSArray(to_kind); | |
|
Toon Verwaest
2013/02/13 15:14:51
Again; update type feedback in the cell.
mvstanton
2013/02/19 11:04:08
Done.
| |
| 235 } else { | |
| 236 AllocationSiteMode mode = AllocationSiteInfo::GetMode(kind); | |
| 237 maybe_array = isolate->heap()->AllocateEmptyJSArray(kind, | |
| 238 mode, | |
| 239 &type_info); | |
| 240 } | |
| 241 if (!maybe_array->To(&array)) return maybe_array; | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 if (array == NULL) { | |
| 246 maybe_array = isolate->heap()->AllocateEmptyJSArray(kind); | |
| 247 if (!maybe_array->To(&array)) return maybe_array; | |
| 248 } | |
| 249 | |
| 250 maybe_array = ArrayConstructInitializeElements(array, caller_args); | |
| 251 if (maybe_array->IsFailure()) return maybe_array; | |
| 252 return array; | |
| 253 } | |
| 254 | |
| 255 | |
| 189 static MaybeObject* ArrayCodeGenericCommon(Arguments* args, | 256 static MaybeObject* ArrayCodeGenericCommon(Arguments* args, |
| 190 Isolate* isolate, | 257 Isolate* isolate, |
| 191 JSFunction* constructor) { | 258 JSFunction* constructor) { |
| 259 ASSERT(args->length() >= 1); | |
| 192 Heap* heap = isolate->heap(); | 260 Heap* heap = isolate->heap(); |
| 193 isolate->counters()->array_function_runtime()->Increment(); | 261 isolate->counters()->array_function_runtime()->Increment(); |
| 194 | 262 |
| 195 JSArray* array; | 263 JSArray* array; |
| 196 if (CalledAsConstructor(isolate)) { | 264 if (CalledAsConstructor(isolate)) { |
| 197 array = JSArray::cast((*args)[0]); | 265 array = JSArray::cast((*args)[0]); |
| 198 // Initialize elements and length in case later allocations fail so that the | 266 // Initialize elements and length in case later allocations fail so that the |
| 199 // array object is initialized in a valid state. | 267 // array object is initialized in a valid state. |
| 200 array->set_length(Smi::FromInt(0)); | 268 array->set_length(Smi::FromInt(0)); |
| 201 array->set_elements(heap->empty_fixed_array()); | 269 array->set_elements(heap->empty_fixed_array()); |
| 270 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(array); | |
| 271 ElementsKind to_kind = array->GetElementsKind(); | |
| 272 if (info != NULL && info->GetElementsKindPayload(&to_kind)) { | |
| 273 if (IsMoreGeneralElementsKindTransition(array->GetElementsKind(), | |
| 274 to_kind)) { | |
| 275 // We have advice that we should change the elements kind | |
| 276 if (FLAG_trace_track_allocation_sites) { | |
| 277 PrintF("AllocationSiteInfo: pre-transitioning array %p(%s->%s)\n", | |
| 278 reinterpret_cast<void*>(array), | |
| 279 ElementsKindToString(array->GetElementsKind()), | |
| 280 ElementsKindToString(to_kind)); | |
| 281 } | |
| 282 | |
| 283 MaybeObject* maybe_array = | |
| 284 array->TransitionElementsKind(to_kind); | |
| 285 if (maybe_array->IsFailure()) return maybe_array; | |
| 286 } | |
| 287 } | |
| 288 | |
| 202 if (!FLAG_smi_only_arrays) { | 289 if (!FLAG_smi_only_arrays) { |
| 203 Context* native_context = isolate->context()->native_context(); | 290 Context* native_context = isolate->context()->native_context(); |
| 204 if (array->GetElementsKind() == GetInitialFastElementsKind() && | 291 if (array->GetElementsKind() == GetInitialFastElementsKind() && |
| 205 !native_context->js_array_maps()->IsUndefined()) { | 292 !native_context->js_array_maps()->IsUndefined()) { |
| 206 FixedArray* map_array = | 293 FixedArray* map_array = |
| 207 FixedArray::cast(native_context->js_array_maps()); | 294 FixedArray::cast(native_context->js_array_maps()); |
| 208 array->set_map(Map::cast(map_array-> | 295 array->set_map(Map::cast(map_array-> |
| 209 get(TERMINAL_FAST_ELEMENTS_KIND))); | 296 get(TERMINAL_FAST_ELEMENTS_KIND))); |
| 210 } | 297 } |
| 211 } | 298 } |
| 212 } else { | 299 } else { |
| 213 // Allocate the JS Array | 300 // Allocate the JS Array |
| 301 // TODO(mvstanton): There is no allocation info advice for this case. | |
| 302 // How to address? | |
| 214 MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); | 303 MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); |
| 215 if (!maybe_obj->To(&array)) return maybe_obj; | 304 if (!maybe_obj->To(&array)) return maybe_obj; |
| 216 } | 305 } |
| 217 | 306 |
| 218 // Optimize the case where there is one argument and the argument is a | 307 Arguments adjusted_arguments(args->length() - 1, args->arguments() - 1); |
| 219 // small smi. | 308 ASSERT(adjusted_arguments.length() < 1 || |
| 220 if (args->length() == 2) { | 309 adjusted_arguments[0] == (*args)[1]); |
| 221 Object* obj = (*args)[1]; | 310 { MaybeObject* maybe_obj = ArrayConstructInitializeElements(array, |
| 222 if (obj->IsSmi()) { | 311 &adjusted_arguments); |
| 223 int len = Smi::cast(obj)->value(); | 312 if (!maybe_obj->To(&array)) return maybe_obj; |
| 224 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { | |
| 225 Object* fixed_array; | |
| 226 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len); | |
| 227 if (!maybe_obj->ToObject(&fixed_array)) return maybe_obj; | |
| 228 } | |
| 229 ElementsKind elements_kind = array->GetElementsKind(); | |
| 230 if (!IsFastHoleyElementsKind(elements_kind)) { | |
| 231 elements_kind = GetHoleyElementsKind(elements_kind); | |
| 232 MaybeObject* maybe_array = | |
| 233 array->TransitionElementsKind(elements_kind); | |
| 234 if (maybe_array->IsFailure()) return maybe_array; | |
| 235 } | |
| 236 // We do not use SetContent to skip the unnecessary elements type check. | |
| 237 array->set_elements(FixedArray::cast(fixed_array)); | |
| 238 array->set_length(Smi::cast(obj)); | |
| 239 return array; | |
| 240 } | |
| 241 } | |
| 242 // Take the argument as the length. | |
| 243 { MaybeObject* maybe_obj = array->Initialize(0); | |
| 244 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 245 } | |
| 246 return array->SetElementsLength((*args)[1]); | |
| 247 } | 313 } |
| 248 | 314 |
| 249 // Optimize the case where there are no parameters passed. | |
| 250 if (args->length() == 1) { | |
| 251 return array->Initialize(JSArray::kPreallocatedArrayElements); | |
| 252 } | |
| 253 | |
| 254 // Set length and elements on the array. | |
| 255 int number_of_elements = args->length() - 1; | |
| 256 MaybeObject* maybe_object = | |
| 257 array->EnsureCanContainElements(args, 1, number_of_elements, | |
| 258 ALLOW_CONVERTED_DOUBLE_ELEMENTS); | |
| 259 if (maybe_object->IsFailure()) return maybe_object; | |
| 260 | |
| 261 // Allocate an appropriately typed elements array. | |
| 262 MaybeObject* maybe_elms; | |
| 263 ElementsKind elements_kind = array->GetElementsKind(); | |
| 264 if (IsFastDoubleElementsKind(elements_kind)) { | |
| 265 maybe_elms = heap->AllocateUninitializedFixedDoubleArray( | |
| 266 number_of_elements); | |
| 267 } else { | |
| 268 maybe_elms = heap->AllocateFixedArrayWithHoles(number_of_elements); | |
| 269 } | |
| 270 FixedArrayBase* elms; | |
| 271 if (!maybe_elms->To(&elms)) return maybe_elms; | |
| 272 | |
| 273 // Fill in the content | |
| 274 switch (array->GetElementsKind()) { | |
| 275 case FAST_HOLEY_SMI_ELEMENTS: | |
| 276 case FAST_SMI_ELEMENTS: { | |
| 277 FixedArray* smi_elms = FixedArray::cast(elms); | |
| 278 for (int index = 0; index < number_of_elements; index++) { | |
| 279 smi_elms->set(index, (*args)[index+1], SKIP_WRITE_BARRIER); | |
| 280 } | |
| 281 break; | |
| 282 } | |
| 283 case FAST_HOLEY_ELEMENTS: | |
| 284 case FAST_ELEMENTS: { | |
| 285 AssertNoAllocation no_gc; | |
| 286 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | |
| 287 FixedArray* object_elms = FixedArray::cast(elms); | |
| 288 for (int index = 0; index < number_of_elements; index++) { | |
| 289 object_elms->set(index, (*args)[index+1], mode); | |
| 290 } | |
| 291 break; | |
| 292 } | |
| 293 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 294 case FAST_DOUBLE_ELEMENTS: { | |
| 295 FixedDoubleArray* double_elms = FixedDoubleArray::cast(elms); | |
| 296 for (int index = 0; index < number_of_elements; index++) { | |
| 297 double_elms->set(index, (*args)[index+1]->Number()); | |
| 298 } | |
| 299 break; | |
| 300 } | |
| 301 default: | |
| 302 UNREACHABLE(); | |
| 303 break; | |
| 304 } | |
| 305 | |
| 306 array->set_elements(elms); | |
| 307 array->set_length(Smi::FromInt(number_of_elements)); | |
| 308 return array; | 315 return array; |
| 309 } | 316 } |
| 310 | 317 |
| 311 | 318 |
| 312 BUILTIN(InternalArrayCodeGeneric) { | 319 BUILTIN(InternalArrayCodeGeneric) { |
| 313 return ArrayCodeGenericCommon( | 320 return ArrayCodeGenericCommon( |
| 314 &args, | 321 &args, |
| 315 isolate, | 322 isolate, |
| 316 isolate->context()->native_context()->internal_array_function()); | 323 isolate->context()->native_context()->internal_array_function()); |
| 317 } | 324 } |
| (...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1169 // boxing doubles may cause incremental marking. | 1176 // boxing doubles may cause incremental marking. |
| 1170 ArrayStorageAllocationMode mode = | 1177 ArrayStorageAllocationMode mode = |
| 1171 has_double && IsFastObjectElementsKind(elements_kind) | 1178 has_double && IsFastObjectElementsKind(elements_kind) |
| 1172 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; | 1179 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; |
| 1173 JSArray* result_array; | 1180 JSArray* result_array; |
| 1174 // Allocate result. | 1181 // Allocate result. |
| 1175 MaybeObject* maybe_array = | 1182 MaybeObject* maybe_array = |
| 1176 heap->AllocateJSArrayAndStorage(elements_kind, | 1183 heap->AllocateJSArrayAndStorage(elements_kind, |
| 1177 result_len, | 1184 result_len, |
| 1178 result_len, | 1185 result_len, |
| 1186 DONT_TRACK_ALLOCATION_SITE, | |
| 1187 NULL, | |
| 1179 mode); | 1188 mode); |
| 1180 if (!maybe_array->To(&result_array)) return maybe_array; | 1189 if (!maybe_array->To(&result_array)) return maybe_array; |
| 1181 if (result_len == 0) return result_array; | 1190 if (result_len == 0) return result_array; |
| 1182 | 1191 |
| 1183 int j = 0; | 1192 int j = 0; |
| 1184 FixedArrayBase* storage = result_array->elements(); | 1193 FixedArrayBase* storage = result_array->elements(); |
| 1185 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 1194 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
| 1186 for (int i = 0; i < n_arguments; i++) { | 1195 for (int i = 0; i < n_arguments; i++) { |
| 1187 JSArray* array = JSArray::cast(args[i]); | 1196 JSArray* array = JSArray::cast(args[i]); |
| 1188 int len = Smi::cast(array->length())->value(); | 1197 int len = Smi::cast(array->length())->value(); |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1875 return Handle<Code>(code_address); \ | 1884 return Handle<Code>(code_address); \ |
| 1876 } | 1885 } |
| 1877 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1886 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1878 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1887 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1879 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1888 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1880 #undef DEFINE_BUILTIN_ACCESSOR_C | 1889 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1881 #undef DEFINE_BUILTIN_ACCESSOR_A | 1890 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1882 | 1891 |
| 1883 | 1892 |
| 1884 } } // namespace v8::internal | 1893 } } // namespace v8::internal |
| OLD | NEW |