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 |