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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 bool should_transform = | 242 bool should_transform = |
243 !is_result_from_cache && boilerplate->HasFastProperties(); | 243 !is_result_from_cache && boilerplate->HasFastProperties(); |
244 if (should_transform || has_function_literal) { | 244 if (should_transform || has_function_literal) { |
245 // Normalize the properties of object to avoid n^2 behavior | 245 // Normalize the properties of object to avoid n^2 behavior |
246 // when extending the object multiple properties. Indicate the number of | 246 // when extending the object multiple properties. Indicate the number of |
247 // properties to be added. | 247 // properties to be added. |
248 JSObject::NormalizeProperties( | 248 JSObject::NormalizeProperties( |
249 boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2); | 249 boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2); |
250 } | 250 } |
251 | 251 |
| 252 // TODO(verwaest): This does not catch the case where the object stays in fast |
| 253 // most from the beginning. However, since it may go slow by adding |
| 254 // properties, currently only assume we'll ever be fast if we ensure |
| 255 // converting it back to fast mode. |
| 256 bool will_be_fast = should_transform && !has_function_literal; |
252 for (int index = 0; index < length; index +=2) { | 257 for (int index = 0; index < length; index +=2) { |
253 Handle<Object> key(constant_properties->get(index+0), isolate); | 258 Handle<Object> key(constant_properties->get(index+0), isolate); |
254 Handle<Object> value(constant_properties->get(index+1), isolate); | 259 Handle<Object> value(constant_properties->get(index+1), isolate); |
255 if (value->IsFixedArray()) { | 260 if (value->IsFixedArray()) { |
256 // The value contains the constant_properties of a | 261 // The value contains the constant_properties of a |
257 // simple object or array literal. | 262 // simple object or array literal. |
258 Handle<FixedArray> array = Handle<FixedArray>::cast(value); | 263 Handle<FixedArray> array = Handle<FixedArray>::cast(value); |
259 value = CreateLiteralBoilerplate(isolate, literals, array); | 264 value = CreateLiteralBoilerplate(isolate, literals, array); |
260 if (value.is_null()) return value; | 265 if (value.is_null()) return value; |
| 266 } else if (value->IsUndefined()) { |
| 267 // TODO(verwaest): Support storage types in the boilerplate. |
| 268 // if (will_be_fast) { |
| 269 // value = isolate->factory()->the_hole_value(); |
| 270 // } else { |
| 271 // value = Handle<Object>(Smi::FromInt(0), isolate); |
| 272 // } |
261 } | 273 } |
262 Handle<Object> result; | 274 Handle<Object> result; |
263 uint32_t element_index = 0; | 275 uint32_t element_index = 0; |
264 if (key->IsInternalizedString()) { | 276 if (key->IsInternalizedString()) { |
265 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { | 277 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { |
266 // Array index as string (uint32). | 278 // Array index as string (uint32). |
267 result = JSObject::SetOwnElement( | 279 result = JSObject::SetOwnElement( |
268 boilerplate, element_index, value, kNonStrictMode); | 280 boilerplate, element_index, value, kNonStrictMode); |
269 } else { | 281 } else { |
270 Handle<String> name(String::cast(*key)); | 282 Handle<String> name(String::cast(*key)); |
(...skipping 21 matching lines...) Expand all Loading... |
292 // exception, the exception is converted to an empty handle in | 304 // exception, the exception is converted to an empty handle in |
293 // the handle based operations. In that case, we need to | 305 // the handle based operations. In that case, we need to |
294 // convert back to an exception. | 306 // convert back to an exception. |
295 if (result.is_null()) return result; | 307 if (result.is_null()) return result; |
296 } | 308 } |
297 | 309 |
298 // Transform to fast properties if necessary. For object literals with | 310 // Transform to fast properties if necessary. For object literals with |
299 // containing function literals we defer this operation until after all | 311 // containing function literals we defer this operation until after all |
300 // computed properties have been assigned so that we can generate | 312 // computed properties have been assigned so that we can generate |
301 // constant function properties. | 313 // constant function properties. |
302 if (should_transform && !has_function_literal) { | 314 if (will_be_fast) { |
303 JSObject::TransformToFastProperties( | 315 JSObject::TransformToFastProperties( |
304 boilerplate, boilerplate->map()->unused_property_fields()); | 316 boilerplate, boilerplate->map()->unused_property_fields()); |
305 } | 317 } |
306 | 318 |
307 return boilerplate; | 319 return boilerplate; |
308 } | 320 } |
309 | 321 |
310 | 322 |
311 MaybeObject* TransitionElements(Handle<Object> object, | 323 MaybeObject* TransitionElements(Handle<Object> object, |
312 ElementsKind to_kind, | 324 ElementsKind to_kind, |
(...skipping 1975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2288 | 2300 |
2289 function->set_map(new_map); | 2301 function->set_map(new_map); |
2290 } else { // Dictionary properties. | 2302 } else { // Dictionary properties. |
2291 // Directly manipulate the property details. | 2303 // Directly manipulate the property details. |
2292 int entry = function->property_dictionary()->FindEntry(name); | 2304 int entry = function->property_dictionary()->FindEntry(name); |
2293 ASSERT(entry != NameDictionary::kNotFound); | 2305 ASSERT(entry != NameDictionary::kNotFound); |
2294 PropertyDetails details = function->property_dictionary()->DetailsAt(entry); | 2306 PropertyDetails details = function->property_dictionary()->DetailsAt(entry); |
2295 PropertyDetails new_details( | 2307 PropertyDetails new_details( |
2296 static_cast<PropertyAttributes>(details.attributes() | READ_ONLY), | 2308 static_cast<PropertyAttributes>(details.attributes() | READ_ONLY), |
2297 details.type(), | 2309 details.type(), |
| 2310 Representation::None(), |
2298 details.dictionary_index()); | 2311 details.dictionary_index()); |
2299 function->property_dictionary()->DetailsAtPut(entry, new_details); | 2312 function->property_dictionary()->DetailsAtPut(entry, new_details); |
2300 } | 2313 } |
2301 return function; | 2314 return function; |
2302 } | 2315 } |
2303 | 2316 |
2304 | 2317 |
2305 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) { | 2318 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) { |
2306 NoHandleAllocation ha(isolate); | 2319 NoHandleAllocation ha(isolate); |
2307 ASSERT(args.length() == 1); | 2320 ASSERT(args.length() == 1); |
(...skipping 5168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7476 Execution::New(Handle<JSFunction>::cast(bound_function), | 7489 Execution::New(Handle<JSFunction>::cast(bound_function), |
7477 total_argc, *param_data, &exception); | 7490 total_argc, *param_data, &exception); |
7478 if (exception) { | 7491 if (exception) { |
7479 return Failure::Exception(); | 7492 return Failure::Exception(); |
7480 } | 7493 } |
7481 ASSERT(!result.is_null()); | 7494 ASSERT(!result.is_null()); |
7482 return *result; | 7495 return *result; |
7483 } | 7496 } |
7484 | 7497 |
7485 | 7498 |
7486 static void TrySettingInlineConstructStub(Isolate* isolate, | 7499 // static void TrySettingInlineConstructStub(Isolate* isolate, |
7487 Handle<JSFunction> function) { | 7500 // Handle<JSFunction> function) { |
7488 Handle<Object> prototype = isolate->factory()->null_value(); | 7501 // Handle<Object> prototype = isolate->factory()->null_value(); |
7489 if (function->has_instance_prototype()) { | 7502 // if (function->has_instance_prototype()) { |
7490 prototype = Handle<Object>(function->instance_prototype(), isolate); | 7503 // prototype = Handle<Object>(function->instance_prototype(), isolate); |
7491 } | 7504 // } |
7492 if (function->shared()->CanGenerateInlineConstructor(*prototype)) { | 7505 // if (function->shared()->CanGenerateInlineConstructor(*prototype)) { |
7493 ConstructStubCompiler compiler(isolate); | 7506 // ConstructStubCompiler compiler(isolate); |
7494 Handle<Code> code = compiler.CompileConstructStub(function); | 7507 // Handle<Code> code = compiler.CompileConstructStub(function); |
7495 function->shared()->set_construct_stub(*code); | 7508 // function->shared()->set_construct_stub(*code); |
7496 } | 7509 // } |
7497 } | 7510 // } |
7498 | 7511 |
7499 | 7512 |
7500 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) { | 7513 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) { |
7501 HandleScope scope(isolate); | 7514 HandleScope scope(isolate); |
7502 ASSERT(args.length() == 1); | 7515 ASSERT(args.length() == 1); |
7503 | 7516 |
7504 Handle<Object> constructor = args.at<Object>(0); | 7517 Handle<Object> constructor = args.at<Object>(0); |
7505 | 7518 |
7506 // If the constructor isn't a proper function we throw a type error. | 7519 // If the constructor isn't a proper function we throw a type error. |
7507 if (!constructor->IsJSFunction()) { | 7520 if (!constructor->IsJSFunction()) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7553 | 7566 |
7554 Handle<SharedFunctionInfo> shared(function->shared(), isolate); | 7567 Handle<SharedFunctionInfo> shared(function->shared(), isolate); |
7555 if (!function->has_initial_map() && | 7568 if (!function->has_initial_map() && |
7556 shared->IsInobjectSlackTrackingInProgress()) { | 7569 shared->IsInobjectSlackTrackingInProgress()) { |
7557 // The tracking is already in progress for another function. We can only | 7570 // The tracking is already in progress for another function. We can only |
7558 // track one initial_map at a time, so we force the completion before the | 7571 // track one initial_map at a time, so we force the completion before the |
7559 // function is called as a constructor for the first time. | 7572 // function is called as a constructor for the first time. |
7560 shared->CompleteInobjectSlackTracking(); | 7573 shared->CompleteInobjectSlackTracking(); |
7561 } | 7574 } |
7562 | 7575 |
7563 bool first_allocation = !shared->live_objects_may_exist(); | 7576 // bool first_allocation = !shared->live_objects_may_exist(); |
7564 Handle<JSObject> result = isolate->factory()->NewJSObject(function); | 7577 Handle<JSObject> result = isolate->factory()->NewJSObject(function); |
7565 RETURN_IF_EMPTY_HANDLE(isolate, result); | 7578 RETURN_IF_EMPTY_HANDLE(isolate, result); |
7566 // Delay setting the stub if inobject slack tracking is in progress. | 7579 // Delay setting the stub if inobject slack tracking is in progress. |
7567 if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) { | 7580 // if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) { |
7568 TrySettingInlineConstructStub(isolate, function); | 7581 // TrySettingInlineConstructStub(isolate, function); |
7569 } | 7582 // } |
7570 | 7583 |
7571 isolate->counters()->constructed_objects()->Increment(); | 7584 isolate->counters()->constructed_objects()->Increment(); |
7572 isolate->counters()->constructed_objects_runtime()->Increment(); | 7585 isolate->counters()->constructed_objects_runtime()->Increment(); |
7573 | 7586 |
7574 return *result; | 7587 return *result; |
7575 } | 7588 } |
7576 | 7589 |
7577 | 7590 |
7578 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) { | 7591 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) { |
7579 HandleScope scope(isolate); | 7592 HandleScope scope(isolate); |
7580 ASSERT(args.length() == 1); | 7593 ASSERT(args.length() == 1); |
7581 | 7594 |
7582 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 7595 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); |
7583 function->shared()->CompleteInobjectSlackTracking(); | 7596 function->shared()->CompleteInobjectSlackTracking(); |
7584 TrySettingInlineConstructStub(isolate, function); | 7597 // TrySettingInlineConstructStub(isolate, function); |
7585 | 7598 |
7586 return isolate->heap()->undefined_value(); | 7599 return isolate->heap()->undefined_value(); |
7587 } | 7600 } |
7588 | 7601 |
7589 | 7602 |
7590 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) { | 7603 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) { |
7591 HandleScope scope(isolate); | 7604 HandleScope scope(isolate); |
7592 ASSERT(args.length() == 1); | 7605 ASSERT(args.length() == 1); |
7593 | 7606 |
7594 Handle<JSFunction> function = args.at<JSFunction>(0); | 7607 Handle<JSFunction> function = args.at<JSFunction>(0); |
(...skipping 2455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10050 if (name->AsArrayIndex(&index)) { | 10063 if (name->AsArrayIndex(&index)) { |
10051 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2); | 10064 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2); |
10052 Object* element_or_char; | 10065 Object* element_or_char; |
10053 { MaybeObject* maybe_element_or_char = | 10066 { MaybeObject* maybe_element_or_char = |
10054 Runtime::GetElementOrCharAt(isolate, obj, index); | 10067 Runtime::GetElementOrCharAt(isolate, obj, index); |
10055 if (!maybe_element_or_char->ToObject(&element_or_char)) { | 10068 if (!maybe_element_or_char->ToObject(&element_or_char)) { |
10056 return maybe_element_or_char; | 10069 return maybe_element_or_char; |
10057 } | 10070 } |
10058 } | 10071 } |
10059 details->set(0, element_or_char); | 10072 details->set(0, element_or_char); |
10060 details->set(1, PropertyDetails(NONE, NORMAL).AsSmi()); | 10073 details->set( |
| 10074 1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi()); |
10061 return *isolate->factory()->NewJSArrayWithElements(details); | 10075 return *isolate->factory()->NewJSArrayWithElements(details); |
10062 } | 10076 } |
10063 | 10077 |
10064 // Find the number of objects making up this. | 10078 // Find the number of objects making up this. |
10065 int length = LocalPrototypeChainLength(*obj); | 10079 int length = LocalPrototypeChainLength(*obj); |
10066 | 10080 |
10067 // Try local lookup on each of the objects. | 10081 // Try local lookup on each of the objects. |
10068 Handle<JSObject> jsproto = obj; | 10082 Handle<JSObject> jsproto = obj; |
10069 for (int i = 0; i < length; i++) { | 10083 for (int i = 0; i < length; i++) { |
10070 LookupResult result(isolate); | 10084 LookupResult result(isolate); |
(...skipping 3168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13239 for (int i = 0; i < kNumFunctions; ++i) { | 13253 for (int i = 0; i < kNumFunctions; ++i) { |
13240 Object* name_string; | 13254 Object* name_string; |
13241 { MaybeObject* maybe_name_string = | 13255 { MaybeObject* maybe_name_string = |
13242 heap->InternalizeUtf8String(kIntrinsicFunctions[i].name); | 13256 heap->InternalizeUtf8String(kIntrinsicFunctions[i].name); |
13243 if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string; | 13257 if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string; |
13244 } | 13258 } |
13245 NameDictionary* name_dictionary = NameDictionary::cast(dictionary); | 13259 NameDictionary* name_dictionary = NameDictionary::cast(dictionary); |
13246 { MaybeObject* maybe_dictionary = name_dictionary->Add( | 13260 { MaybeObject* maybe_dictionary = name_dictionary->Add( |
13247 String::cast(name_string), | 13261 String::cast(name_string), |
13248 Smi::FromInt(i), | 13262 Smi::FromInt(i), |
13249 PropertyDetails(NONE, NORMAL)); | 13263 PropertyDetails(NONE, NORMAL, Representation::None())); |
13250 if (!maybe_dictionary->ToObject(&dictionary)) { | 13264 if (!maybe_dictionary->ToObject(&dictionary)) { |
13251 // Non-recoverable failure. Calling code must restart heap | 13265 // Non-recoverable failure. Calling code must restart heap |
13252 // initialization. | 13266 // initialization. |
13253 return maybe_dictionary; | 13267 return maybe_dictionary; |
13254 } | 13268 } |
13255 } | 13269 } |
13256 } | 13270 } |
13257 return dictionary; | 13271 return dictionary; |
13258 } | 13272 } |
13259 | 13273 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13291 // Handle last resort GC and make sure to allow future allocations | 13305 // Handle last resort GC and make sure to allow future allocations |
13292 // to grow the heap without causing GCs (if possible). | 13306 // to grow the heap without causing GCs (if possible). |
13293 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13307 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13294 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13308 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13295 "Runtime::PerformGC"); | 13309 "Runtime::PerformGC"); |
13296 } | 13310 } |
13297 } | 13311 } |
13298 | 13312 |
13299 | 13313 |
13300 } } // namespace v8::internal | 13314 } } // namespace v8::internal |
OLD | NEW |