| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 25 matching lines...) Expand all Loading... |
| 36 #include "execution.h" | 36 #include "execution.h" |
| 37 #include "global-handles.h" | 37 #include "global-handles.h" |
| 38 #include "natives.h" | 38 #include "natives.h" |
| 39 #include "runtime.h" | 39 #include "runtime.h" |
| 40 #include "stub-cache.h" | 40 #include "stub-cache.h" |
| 41 | 41 |
| 42 namespace v8 { | 42 namespace v8 { |
| 43 namespace internal { | 43 namespace internal { |
| 44 | 44 |
| 45 | 45 |
| 46 v8::ImplementationUtilities::HandleScopeData HandleScope::current_ = | |
| 47 { -1, NULL, NULL }; | |
| 48 | |
| 49 | 46 |
| 50 int HandleScope::NumberOfHandles() { | 47 int HandleScope::NumberOfHandles() { |
| 51 int n = HandleScopeImplementer::instance()->blocks()->length(); | 48 int n = HandleScopeImplementer::instance()->blocks()->length(); |
| 52 if (n == 0) return 0; | 49 if (n == 0) return 0; |
| 53 return ((n - 1) * kHandleBlockSize) + static_cast<int>( | 50 return ((n - 1) * kHandleBlockSize) + static_cast<int>( |
| 54 (current_.next - HandleScopeImplementer::instance()->blocks()->last())); | 51 (v8_context()->handle_scope_data_.next - |
| 52 HandleScopeImplementer::instance()->blocks()->last())); |
| 55 } | 53 } |
| 56 | 54 |
| 57 | 55 |
| 58 Object** HandleScope::Extend() { | 56 Object** HandleScope::Extend() { |
| 59 Object** result = current_.next; | 57 ImplementationUtilities::HandleScopeData& current = |
| 58 v8_context()->handle_scope_data_; |
| 59 Object** result = current.next; |
| 60 | 60 |
| 61 ASSERT(result == current_.limit); | 61 ASSERT(result == current.limit); |
| 62 // Make sure there's at least one scope on the stack and that the | 62 // Make sure there's at least one scope on the stack and that the |
| 63 // top of the scope stack isn't a barrier. | 63 // top of the scope stack isn't a barrier. |
| 64 if (current_.extensions < 0) { | 64 if (current.extensions < 0) { |
| 65 Utils::ReportApiFailure("v8::HandleScope::CreateHandle()", | 65 Utils::ReportApiFailure("v8::HandleScope::CreateHandle()", |
| 66 "Cannot create a handle without a HandleScope"); | 66 "Cannot create a handle without a HandleScope"); |
| 67 return NULL; | 67 return NULL; |
| 68 } | 68 } |
| 69 HandleScopeImplementer* impl = HandleScopeImplementer::instance(); | 69 HandleScopeImplementer* impl = HandleScopeImplementer::instance(); |
| 70 // If there's more room in the last block, we use that. This is used | 70 // If there's more room in the last block, we use that. This is used |
| 71 // for fast creation of scopes after scope barriers. | 71 // for fast creation of scopes after scope barriers. |
| 72 if (!impl->blocks()->is_empty()) { | 72 if (!impl->blocks()->is_empty()) { |
| 73 Object** limit = &impl->blocks()->last()[kHandleBlockSize]; | 73 Object** limit = &impl->blocks()->last()[kHandleBlockSize]; |
| 74 if (current_.limit != limit) { | 74 if (current.limit != limit) { |
| 75 current_.limit = limit; | 75 current.limit = limit; |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 | 78 |
| 79 // If we still haven't found a slot for the handle, we extend the | 79 // If we still haven't found a slot for the handle, we extend the |
| 80 // current handle scope by allocating a new handle block. | 80 // current handle scope by allocating a new handle block. |
| 81 if (result == current_.limit) { | 81 if (result == current.limit) { |
| 82 // If there's a spare block, use it for growing the current scope. | 82 // If there's a spare block, use it for growing the current scope. |
| 83 result = impl->GetSpareOrNewBlock(); | 83 result = impl->GetSpareOrNewBlock(); |
| 84 // Add the extension to the global list of blocks, but count the | 84 // Add the extension to the global list of blocks, but count the |
| 85 // extension as part of the current scope. | 85 // extension as part of the current scope. |
| 86 impl->blocks()->Add(result); | 86 impl->blocks()->Add(result); |
| 87 current_.extensions++; | 87 current.extensions++; |
| 88 current_.limit = &result[kHandleBlockSize]; | 88 current.limit = &result[kHandleBlockSize]; |
| 89 } | 89 } |
| 90 | 90 |
| 91 return result; | 91 return result; |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 void HandleScope::DeleteExtensions() { | 95 void HandleScope::DeleteExtensions() { |
| 96 ASSERT(current_.extensions != 0); | 96 ImplementationUtilities::HandleScopeData& current = |
| 97 HandleScopeImplementer::instance()->DeleteExtensions(current_.extensions); | 97 v8_context()->handle_scope_data_; |
| 98 ASSERT(current.extensions != 0); |
| 99 HandleScopeImplementer::instance()->DeleteExtensions(current.extensions); |
| 98 } | 100 } |
| 99 | 101 |
| 100 | 102 |
| 101 void HandleScope::ZapRange(Object** start, Object** end) { | 103 void HandleScope::ZapRange(Object** start, Object** end) { |
| 102 if (start == NULL) return; | 104 if (start == NULL) return; |
| 103 for (Object** p = start; p < end; p++) { | 105 for (Object** p = start; p < end; p++) { |
| 104 *reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue; | 106 *reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue; |
| 105 } | 107 } |
| 106 } | 108 } |
| 107 | 109 |
| 108 | 110 |
| 109 Address HandleScope::current_extensions_address() { | 111 Address HandleScope::current_extensions_address() { |
| 110 return reinterpret_cast<Address>(¤t_.extensions); | 112 return reinterpret_cast<Address>( |
| 113 &v8_context()->handle_scope_data_.extensions); |
| 111 } | 114 } |
| 112 | 115 |
| 113 | 116 |
| 114 Address HandleScope::current_next_address() { | 117 Address HandleScope::current_next_address() { |
| 115 return reinterpret_cast<Address>(¤t_.next); | 118 return reinterpret_cast<Address>(&v8_context()->handle_scope_data_.next); |
| 116 } | 119 } |
| 117 | 120 |
| 118 | 121 |
| 119 Address HandleScope::current_limit_address() { | 122 Address HandleScope::current_limit_address() { |
| 120 return reinterpret_cast<Address>(¤t_.limit); | 123 return reinterpret_cast<Address>(&v8_context()->handle_scope_data_.limit); |
| 121 } | 124 } |
| 122 | 125 |
| 123 | 126 |
| 124 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content, | 127 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content, |
| 125 Handle<JSArray> array) { | 128 Handle<JSArray> array) { |
| 126 CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray); | 129 CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray); |
| 127 } | 130 } |
| 128 | 131 |
| 129 | 132 |
| 130 Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first, | 133 Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first, |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 // Weak reference callbacks are called as if from outside V8. We | 394 // Weak reference callbacks are called as if from outside V8. We |
| 392 // need to reeenter to unprotect the heap. | 395 // need to reeenter to unprotect the heap. |
| 393 VMState state(OTHER); | 396 VMState state(OTHER); |
| 394 #endif | 397 #endif |
| 395 Handle<Object> cache = Utils::OpenHandle(*handle); | 398 Handle<Object> cache = Utils::OpenHandle(*handle); |
| 396 JSValue* wrapper = JSValue::cast(*cache); | 399 JSValue* wrapper = JSValue::cast(*cache); |
| 397 Proxy* proxy = Script::cast(wrapper->value())->wrapper(); | 400 Proxy* proxy = Script::cast(wrapper->value())->wrapper(); |
| 398 ASSERT(proxy->proxy() == reinterpret_cast<Address>(cache.location())); | 401 ASSERT(proxy->proxy() == reinterpret_cast<Address>(cache.location())); |
| 399 proxy->set_proxy(0); | 402 proxy->set_proxy(0); |
| 400 GlobalHandles::Destroy(cache.location()); | 403 GlobalHandles::Destroy(cache.location()); |
| 401 Counters::script_wrappers.Decrement(); | 404 DEC_COUNTER(script_wrappers); |
| 402 } | 405 } |
| 403 | 406 |
| 404 | 407 |
| 405 Handle<JSValue> GetScriptWrapper(Handle<Script> script) { | 408 Handle<JSValue> GetScriptWrapper(Handle<Script> script) { |
| 406 if (script->wrapper()->proxy() != NULL) { | 409 if (script->wrapper()->proxy() != NULL) { |
| 407 // Return the script wrapper directly from the cache. | 410 // Return the script wrapper directly from the cache. |
| 408 return Handle<JSValue>( | 411 return Handle<JSValue>( |
| 409 reinterpret_cast<JSValue**>(script->wrapper()->proxy())); | 412 reinterpret_cast<JSValue**>(script->wrapper()->proxy())); |
| 410 } | 413 } |
| 411 | 414 |
| 412 // Construct a new script wrapper. | 415 // Construct a new script wrapper. |
| 413 Counters::script_wrappers.Increment(); | 416 INC_COUNTER(script_wrappers); |
| 414 Handle<JSFunction> constructor = Top::script_function(); | 417 Handle<JSFunction> constructor = Top::script_function(); |
| 415 Handle<JSValue> result = | 418 Handle<JSValue> result = |
| 416 Handle<JSValue>::cast(Factory::NewJSObject(constructor)); | 419 Handle<JSValue>::cast(Factory::NewJSObject(constructor)); |
| 417 result->set_value(*script); | 420 result->set_value(*script); |
| 418 | 421 |
| 419 // Create a new weak global handle and use it to cache the wrapper | 422 // Create a new weak global handle and use it to cache the wrapper |
| 420 // for future use. The cache will automatically be cleared by the | 423 // for future use. The cache will automatically be cleared by the |
| 421 // garbage collector when it is not used anymore. | 424 // garbage collector when it is not used anymore. |
| 422 Handle<Object> handle = GlobalHandles::Create(*result); | 425 Handle<Object> handle = GlobalHandles::Create(*result); |
| 423 GlobalHandles::MakeWeak(handle.location(), NULL, &ClearWrapperCache); | 426 GlobalHandles::MakeWeak(handle.location(), NULL, &ClearWrapperCache); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 // If we only want local properties we bail out after the first | 613 // If we only want local properties we bail out after the first |
| 611 // iteration. | 614 // iteration. |
| 612 if (type == LOCAL_ONLY) | 615 if (type == LOCAL_ONLY) |
| 613 break; | 616 break; |
| 614 } | 617 } |
| 615 return content; | 618 return content; |
| 616 } | 619 } |
| 617 | 620 |
| 618 | 621 |
| 619 Handle<JSArray> GetKeysFor(Handle<JSObject> object) { | 622 Handle<JSArray> GetKeysFor(Handle<JSObject> object) { |
| 620 Counters::for_in.Increment(); | 623 INC_COUNTER(for_in); |
| 621 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object, | 624 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object, |
| 622 INCLUDE_PROTOS); | 625 INCLUDE_PROTOS); |
| 623 return Factory::NewJSArrayWithElements(elements); | 626 return Factory::NewJSArrayWithElements(elements); |
| 624 } | 627 } |
| 625 | 628 |
| 626 | 629 |
| 627 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, | 630 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, |
| 628 bool cache_result) { | 631 bool cache_result) { |
| 629 int index = 0; | 632 int index = 0; |
| 630 if (object->HasFastProperties()) { | 633 if (object->HasFastProperties()) { |
| 631 if (object->map()->instance_descriptors()->HasEnumCache()) { | 634 if (object->map()->instance_descriptors()->HasEnumCache()) { |
| 632 Counters::enum_cache_hits.Increment(); | 635 INC_COUNTER(enum_cache_hits); |
| 633 DescriptorArray* desc = object->map()->instance_descriptors(); | 636 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 634 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache())); | 637 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache())); |
| 635 } | 638 } |
| 636 Counters::enum_cache_misses.Increment(); | 639 INC_COUNTER(enum_cache_misses); |
| 637 int num_enum = object->NumberOfEnumProperties(); | 640 int num_enum = object->NumberOfEnumProperties(); |
| 638 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum); | 641 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum); |
| 639 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum); | 642 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum); |
| 640 Handle<DescriptorArray> descs = | 643 Handle<DescriptorArray> descs = |
| 641 Handle<DescriptorArray>(object->map()->instance_descriptors()); | 644 Handle<DescriptorArray>(object->map()->instance_descriptors()); |
| 642 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 645 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 643 if (descs->IsProperty(i) && !descs->IsDontEnum(i)) { | 646 if (descs->IsProperty(i) && !descs->IsDontEnum(i)) { |
| 644 (*storage)->set(index, descs->GetKey(i)); | 647 (*storage)->set(index, descs->GetKey(i)); |
| 645 PropertyDetails details(descs->GetDetails(i)); | 648 PropertyDetails details(descs->GetDetails(i)); |
| 646 (*sort_array)->set(index, Smi::FromInt(details.index())); | 649 (*sort_array)->set(index, Smi::FromInt(details.index())); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 Handle<Map> new_map = Factory::CopyMapDropTransitions(old_map); | 805 Handle<Map> new_map = Factory::CopyMapDropTransitions(old_map); |
| 803 obj->set_map(*new_map); | 806 obj->set_map(*new_map); |
| 804 new_map->set_needs_loading(true); | 807 new_map->set_needs_loading(true); |
| 805 // Store the lazy loading info in the constructor field. We'll | 808 // Store the lazy loading info in the constructor field. We'll |
| 806 // reestablish the constructor from the fixed array after loading. | 809 // reestablish the constructor from the fixed array after loading. |
| 807 new_map->set_constructor(*arr); | 810 new_map->set_constructor(*arr); |
| 808 ASSERT(!obj->IsLoaded()); | 811 ASSERT(!obj->IsLoaded()); |
| 809 } | 812 } |
| 810 | 813 |
| 811 } } // namespace v8::internal | 814 } } // namespace v8::internal |
| OLD | NEW |