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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 Handle<JSFunction> function = args.at<JSFunction>(1); | 196 Handle<JSFunction> function = args.at<JSFunction>(1); |
197 Handle<Object> type_info = args.at<Object>(2); | 197 Handle<Object> type_info = args.at<Object>(2); |
198 | 198 |
199 JSArray* array = NULL; | 199 JSArray* array = NULL; |
200 bool holey = false; | 200 bool holey = false; |
201 if (caller_args->length() == 1 && (*caller_args)[0]->IsSmi()) { | 201 if (caller_args->length() == 1 && (*caller_args)[0]->IsSmi()) { |
202 int value = Smi::cast((*caller_args)[0])->value(); | 202 int value = Smi::cast((*caller_args)[0])->value(); |
203 holey = (value > 0 && value < JSObject::kInitialMaxFastElementArray); | 203 holey = (value > 0 && value < JSObject::kInitialMaxFastElementArray); |
204 } | 204 } |
205 | 205 |
206 // Allocate the initial map if absent. | 206 ASSERT(function->has_initial_map()); |
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 } | |
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(); | 207 ElementsKind kind = function->initial_map()->elements_kind(); |
218 if (holey) { | 208 if (holey) { |
219 kind = GetHoleyElementsKind(kind); | 209 kind = GetHoleyElementsKind(kind); |
220 } | 210 } |
221 | 211 |
222 MaybeObject* maybe_array; | 212 MaybeObject* maybe_array; |
223 if (*type_info != isolate->heap()->undefined_value()) { | 213 if (*type_info != isolate->heap()->undefined_value()) { |
224 ASSERT(type_info->IsJSGlobalPropertyCell()); | |
225 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info); | 214 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info); |
226 if (cell->value()->IsSmi()) { | 215 if (cell->value()->IsSmi()) { |
227 Smi* smi = Smi::cast(cell->value()); | 216 Smi* smi = Smi::cast(cell->value()); |
228 ElementsKind to_kind = static_cast<ElementsKind>(smi->value()); | 217 ElementsKind to_kind = static_cast<ElementsKind>(smi->value()); |
229 if (holey) { | 218 if (holey && !IsFastHoleyElementsKind(to_kind)) { |
230 to_kind = GetHoleyElementsKind(to_kind); | 219 to_kind = GetHoleyElementsKind(to_kind); |
| 220 // Update the allocation site info to reflect the advice alteration. |
| 221 cell->set_value(Smi::FromInt(to_kind)); |
231 } | 222 } |
232 | 223 |
233 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 224 AllocationSiteMode mode = AllocationSiteInfo::GetMode(to_kind); |
234 maybe_array = isolate->heap()->AllocateEmptyJSArray(to_kind); | 225 if (mode == TRACK_ALLOCATION_SITE) { |
| 226 maybe_array = isolate->heap()->AllocateEmptyJSArrayWithAllocationSite( |
| 227 kind, type_info); |
235 } else { | 228 } else { |
236 AllocationSiteMode mode = AllocationSiteInfo::GetMode(kind); | 229 maybe_array = isolate->heap()->AllocateEmptyJSArray(kind); |
237 maybe_array = isolate->heap()->AllocateEmptyJSArray(kind, | |
238 mode, | |
239 &type_info); | |
240 } | 230 } |
241 if (!maybe_array->To(&array)) return maybe_array; | 231 if (!maybe_array->To(&array)) return maybe_array; |
242 } | 232 } |
243 } | 233 } |
244 | 234 |
245 if (array == NULL) { | 235 if (array == NULL) { |
246 maybe_array = isolate->heap()->AllocateEmptyJSArray(kind); | 236 maybe_array = isolate->heap()->AllocateEmptyJSArray(kind); |
247 if (!maybe_array->To(&array)) return maybe_array; | 237 if (!maybe_array->To(&array)) return maybe_array; |
248 } | 238 } |
249 | 239 |
250 maybe_array = ArrayConstructInitializeElements(array, caller_args); | 240 maybe_array = ArrayConstructInitializeElements(array, caller_args); |
251 if (maybe_array->IsFailure()) return maybe_array; | 241 if (maybe_array->IsFailure()) return maybe_array; |
252 return array; | 242 return array; |
253 } | 243 } |
254 | 244 |
255 | 245 |
256 static MaybeObject* ArrayCodeGenericCommon(Arguments* args, | 246 static MaybeObject* ArrayCodeGenericCommon(Arguments* args, |
257 Isolate* isolate, | 247 Isolate* isolate, |
258 JSFunction* constructor) { | 248 JSFunction* constructor) { |
259 ASSERT(args->length() >= 1); | 249 ASSERT(args->length() >= 1); |
260 Heap* heap = isolate->heap(); | 250 Heap* heap = isolate->heap(); |
261 isolate->counters()->array_function_runtime()->Increment(); | 251 isolate->counters()->array_function_runtime()->Increment(); |
262 | 252 |
263 JSArray* array; | 253 JSArray* array; |
264 if (CalledAsConstructor(isolate)) { | 254 if (CalledAsConstructor(isolate)) { |
265 array = JSArray::cast((*args)[0]); | 255 array = JSArray::cast((*args)[0]); |
266 // Initialize elements and length in case later allocations fail so that the | 256 // Initialize elements and length in case later allocations fail so that the |
267 // array object is initialized in a valid state. | 257 // array object is initialized in a valid state. |
268 array->set_length(Smi::FromInt(0)); | 258 MaybeObject* maybe_array = array->Initialize(0); |
269 array->set_elements(heap->empty_fixed_array()); | 259 if (maybe_array->IsFailure()) return maybe_array; |
270 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(array); | 260 |
271 ElementsKind to_kind = array->GetElementsKind(); | 261 if (FLAG_optimize_constructed_arrays) { |
272 if (info != NULL && info->GetElementsKindPayload(&to_kind)) { | 262 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(array); |
273 if (IsMoreGeneralElementsKindTransition(array->GetElementsKind(), | 263 ElementsKind to_kind = array->GetElementsKind(); |
274 to_kind)) { | 264 if (info != NULL && info->GetElementsKindPayload(&to_kind)) { |
275 // We have advice that we should change the elements kind | 265 if (IsMoreGeneralElementsKindTransition(array->GetElementsKind(), |
276 if (FLAG_trace_track_allocation_sites) { | 266 to_kind)) { |
277 PrintF("AllocationSiteInfo: pre-transitioning array %p(%s->%s)\n", | 267 // We have advice that we should change the elements kind |
278 reinterpret_cast<void*>(array), | 268 if (FLAG_trace_track_allocation_sites) { |
279 ElementsKindToString(array->GetElementsKind()), | 269 PrintF("AllocationSiteInfo: pre-transitioning array %p(%s->%s)\n", |
280 ElementsKindToString(to_kind)); | 270 reinterpret_cast<void*>(array), |
| 271 ElementsKindToString(array->GetElementsKind()), |
| 272 ElementsKindToString(to_kind)); |
| 273 } |
| 274 |
| 275 maybe_array = array->TransitionElementsKind(to_kind); |
| 276 if (maybe_array->IsFailure()) return maybe_array; |
281 } | 277 } |
282 | |
283 MaybeObject* maybe_array = | |
284 array->TransitionElementsKind(to_kind); | |
285 if (maybe_array->IsFailure()) return maybe_array; | |
286 } | 278 } |
287 } | 279 } |
288 | 280 |
289 if (!FLAG_smi_only_arrays) { | 281 if (!FLAG_smi_only_arrays) { |
290 Context* native_context = isolate->context()->native_context(); | 282 Context* native_context = isolate->context()->native_context(); |
291 if (array->GetElementsKind() == GetInitialFastElementsKind() && | 283 if (array->GetElementsKind() == GetInitialFastElementsKind() && |
292 !native_context->js_array_maps()->IsUndefined()) { | 284 !native_context->js_array_maps()->IsUndefined()) { |
293 FixedArray* map_array = | 285 FixedArray* map_array = |
294 FixedArray::cast(native_context->js_array_maps()); | 286 FixedArray::cast(native_context->js_array_maps()); |
295 array->set_map(Map::cast(map_array-> | 287 array->set_map(Map::cast(map_array-> |
296 get(TERMINAL_FAST_ELEMENTS_KIND))); | 288 get(TERMINAL_FAST_ELEMENTS_KIND))); |
297 } | 289 } |
298 } | 290 } |
299 } else { | 291 } else { |
300 // Allocate the JS Array | 292 // Allocate the JS Array |
301 // TODO(mvstanton): There is no allocation info advice for this case. | |
302 // How to address? | |
303 MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); | 293 MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); |
304 if (!maybe_obj->To(&array)) return maybe_obj; | 294 if (!maybe_obj->To(&array)) return maybe_obj; |
305 } | 295 } |
306 | 296 |
307 Arguments adjusted_arguments(args->length() - 1, args->arguments() - 1); | 297 Arguments adjusted_arguments(args->length() - 1, args->arguments() - 1); |
308 ASSERT(adjusted_arguments.length() < 1 || | 298 ASSERT(adjusted_arguments.length() < 1 || |
309 adjusted_arguments[0] == (*args)[1]); | 299 adjusted_arguments[0] == (*args)[1]); |
310 { MaybeObject* maybe_obj = ArrayConstructInitializeElements(array, | 300 return ArrayConstructInitializeElements(array, &adjusted_arguments); |
311 &adjusted_arguments); | |
312 if (!maybe_obj->To(&array)) return maybe_obj; | |
313 } | |
314 | |
315 return array; | |
316 } | 301 } |
317 | 302 |
318 | 303 |
319 BUILTIN(InternalArrayCodeGeneric) { | 304 BUILTIN(InternalArrayCodeGeneric) { |
320 return ArrayCodeGenericCommon( | 305 return ArrayCodeGenericCommon( |
321 &args, | 306 &args, |
322 isolate, | 307 isolate, |
323 isolate->context()->native_context()->internal_array_function()); | 308 isolate->context()->native_context()->internal_array_function()); |
324 } | 309 } |
325 | 310 |
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 // boxing doubles may cause incremental marking. | 1161 // boxing doubles may cause incremental marking. |
1177 ArrayStorageAllocationMode mode = | 1162 ArrayStorageAllocationMode mode = |
1178 has_double && IsFastObjectElementsKind(elements_kind) | 1163 has_double && IsFastObjectElementsKind(elements_kind) |
1179 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; | 1164 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; |
1180 JSArray* result_array; | 1165 JSArray* result_array; |
1181 // Allocate result. | 1166 // Allocate result. |
1182 MaybeObject* maybe_array = | 1167 MaybeObject* maybe_array = |
1183 heap->AllocateJSArrayAndStorage(elements_kind, | 1168 heap->AllocateJSArrayAndStorage(elements_kind, |
1184 result_len, | 1169 result_len, |
1185 result_len, | 1170 result_len, |
1186 DONT_TRACK_ALLOCATION_SITE, | |
1187 NULL, | |
1188 mode); | 1171 mode); |
1189 if (!maybe_array->To(&result_array)) return maybe_array; | 1172 if (!maybe_array->To(&result_array)) return maybe_array; |
1190 if (result_len == 0) return result_array; | 1173 if (result_len == 0) return result_array; |
1191 | 1174 |
1192 int j = 0; | 1175 int j = 0; |
1193 FixedArrayBase* storage = result_array->elements(); | 1176 FixedArrayBase* storage = result_array->elements(); |
1194 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 1177 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
1195 for (int i = 0; i < n_arguments; i++) { | 1178 for (int i = 0; i < n_arguments; i++) { |
1196 JSArray* array = JSArray::cast(args[i]); | 1179 JSArray* array = JSArray::cast(args[i]); |
1197 int len = Smi::cast(array->length())->value(); | 1180 int len = Smi::cast(array->length())->value(); |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1884 return Handle<Code>(code_address); \ | 1867 return Handle<Code>(code_address); \ |
1885 } | 1868 } |
1886 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1869 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1887 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1870 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1888 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1871 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1889 #undef DEFINE_BUILTIN_ACCESSOR_C | 1872 #undef DEFINE_BUILTIN_ACCESSOR_C |
1890 #undef DEFINE_BUILTIN_ACCESSOR_A | 1873 #undef DEFINE_BUILTIN_ACCESSOR_A |
1891 | 1874 |
1892 | 1875 |
1893 } } // namespace v8::internal | 1876 } } // namespace v8::internal |
OLD | NEW |