2008-09-09 20:08:45 +00:00
|
|
|
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
2008-07-03 15:10:15 +00:00
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following
|
|
|
|
// disclaimer in the documentation and/or other materials provided
|
|
|
|
// with the distribution.
|
|
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
|
|
// contributors may be used to endorse or promote products derived
|
|
|
|
// from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#ifndef V8_HEAP_H_
|
|
|
|
#define V8_HEAP_H_
|
|
|
|
|
|
|
|
namespace v8 { namespace internal {
|
|
|
|
|
|
|
|
// Defines all the roots in Heap.
|
|
|
|
#define STRONG_ROOT_LIST(V) \
|
|
|
|
V(Map, meta_map) \
|
|
|
|
V(Map, heap_number_map) \
|
|
|
|
V(Map, short_string_map) \
|
|
|
|
V(Map, medium_string_map) \
|
|
|
|
V(Map, long_string_map) \
|
|
|
|
V(Map, short_ascii_string_map) \
|
|
|
|
V(Map, medium_ascii_string_map) \
|
|
|
|
V(Map, long_ascii_string_map) \
|
|
|
|
V(Map, short_symbol_map) \
|
|
|
|
V(Map, medium_symbol_map) \
|
|
|
|
V(Map, long_symbol_map) \
|
|
|
|
V(Map, short_ascii_symbol_map) \
|
|
|
|
V(Map, medium_ascii_symbol_map) \
|
|
|
|
V(Map, long_ascii_symbol_map) \
|
|
|
|
V(Map, short_cons_symbol_map) \
|
|
|
|
V(Map, medium_cons_symbol_map) \
|
|
|
|
V(Map, long_cons_symbol_map) \
|
|
|
|
V(Map, short_cons_ascii_symbol_map) \
|
|
|
|
V(Map, medium_cons_ascii_symbol_map) \
|
|
|
|
V(Map, long_cons_ascii_symbol_map) \
|
|
|
|
V(Map, short_sliced_symbol_map) \
|
|
|
|
V(Map, medium_sliced_symbol_map) \
|
|
|
|
V(Map, long_sliced_symbol_map) \
|
|
|
|
V(Map, short_sliced_ascii_symbol_map) \
|
|
|
|
V(Map, medium_sliced_ascii_symbol_map) \
|
|
|
|
V(Map, long_sliced_ascii_symbol_map) \
|
|
|
|
V(Map, short_external_symbol_map) \
|
|
|
|
V(Map, medium_external_symbol_map) \
|
|
|
|
V(Map, long_external_symbol_map) \
|
|
|
|
V(Map, short_external_ascii_symbol_map) \
|
|
|
|
V(Map, medium_external_ascii_symbol_map) \
|
|
|
|
V(Map, long_external_ascii_symbol_map) \
|
|
|
|
V(Map, short_cons_string_map) \
|
|
|
|
V(Map, medium_cons_string_map) \
|
|
|
|
V(Map, long_cons_string_map) \
|
|
|
|
V(Map, short_cons_ascii_string_map) \
|
|
|
|
V(Map, medium_cons_ascii_string_map) \
|
|
|
|
V(Map, long_cons_ascii_string_map) \
|
|
|
|
V(Map, short_sliced_string_map) \
|
|
|
|
V(Map, medium_sliced_string_map) \
|
|
|
|
V(Map, long_sliced_string_map) \
|
|
|
|
V(Map, short_sliced_ascii_string_map) \
|
|
|
|
V(Map, medium_sliced_ascii_string_map) \
|
|
|
|
V(Map, long_sliced_ascii_string_map) \
|
|
|
|
V(Map, short_external_string_map) \
|
|
|
|
V(Map, medium_external_string_map) \
|
|
|
|
V(Map, long_external_string_map) \
|
|
|
|
V(Map, short_external_ascii_string_map) \
|
|
|
|
V(Map, medium_external_ascii_string_map) \
|
|
|
|
V(Map, long_external_ascii_string_map) \
|
|
|
|
V(Map, undetectable_short_string_map) \
|
|
|
|
V(Map, undetectable_medium_string_map) \
|
|
|
|
V(Map, undetectable_long_string_map) \
|
|
|
|
V(Map, undetectable_short_ascii_string_map) \
|
|
|
|
V(Map, undetectable_medium_ascii_string_map) \
|
|
|
|
V(Map, undetectable_long_ascii_string_map) \
|
|
|
|
V(Map, byte_array_map) \
|
|
|
|
V(Map, fixed_array_map) \
|
|
|
|
V(Map, hash_table_map) \
|
|
|
|
V(Map, context_map) \
|
|
|
|
V(Map, global_context_map) \
|
|
|
|
V(Map, code_map) \
|
|
|
|
V(Map, oddball_map) \
|
|
|
|
V(Map, boilerplate_function_map) \
|
|
|
|
V(Map, shared_function_info_map) \
|
|
|
|
V(Map, proxy_map) \
|
|
|
|
V(Map, one_word_filler_map) \
|
|
|
|
V(Map, two_word_filler_map) \
|
|
|
|
V(Object, nan_value) \
|
|
|
|
V(Object, undefined_value) \
|
|
|
|
V(Object, minus_zero_value) \
|
|
|
|
V(Object, null_value) \
|
|
|
|
V(Object, true_value) \
|
|
|
|
V(Object, false_value) \
|
|
|
|
V(String, empty_string) \
|
|
|
|
V(FixedArray, empty_fixed_array) \
|
2008-08-27 10:11:39 +00:00
|
|
|
V(DescriptorArray, empty_descriptor_array) \
|
2008-07-03 15:10:15 +00:00
|
|
|
V(Object, the_hole_value) \
|
|
|
|
V(Map, neander_map) \
|
|
|
|
V(JSObject, message_listeners) \
|
|
|
|
V(Proxy, prototype_accessors) \
|
|
|
|
V(JSObject, debug_event_listeners) \
|
|
|
|
V(Dictionary, code_stubs) \
|
|
|
|
V(Dictionary, non_monomorphic_cache) \
|
|
|
|
V(Code, js_entry_code) \
|
|
|
|
V(Code, js_construct_entry_code) \
|
|
|
|
V(Code, c_entry_code) \
|
|
|
|
V(Code, c_entry_debug_break_code) \
|
|
|
|
V(FixedArray, number_string_cache) \
|
|
|
|
V(FixedArray, single_character_string_cache) \
|
2008-10-23 07:04:56 +00:00
|
|
|
V(FixedArray, natives_source_cache) \
|
|
|
|
V(Object, keyed_lookup_cache)
|
2008-09-11 10:51:52 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#define ROOT_LIST(V) \
|
|
|
|
STRONG_ROOT_LIST(V) \
|
|
|
|
V(Object, symbol_table)
|
|
|
|
|
|
|
|
#define SYMBOL_LIST(V) \
|
|
|
|
V(Array_symbol, "Array") \
|
|
|
|
V(Object_symbol, "Object") \
|
|
|
|
V(Proto_symbol, "__proto__") \
|
|
|
|
V(StringImpl_symbol, "StringImpl") \
|
|
|
|
V(arguments_symbol, "arguments") \
|
2008-10-17 11:33:04 +00:00
|
|
|
V(Arguments_symbol, "Arguments") \
|
2008-07-03 15:10:15 +00:00
|
|
|
V(arguments_shadow_symbol, ".arguments") \
|
|
|
|
V(call_symbol, "call") \
|
|
|
|
V(apply_symbol, "apply") \
|
|
|
|
V(caller_symbol, "caller") \
|
|
|
|
V(boolean_symbol, "boolean") \
|
2008-10-17 11:33:04 +00:00
|
|
|
V(Boolean_symbol, "Boolean") \
|
2008-07-03 15:10:15 +00:00
|
|
|
V(callee_symbol, "callee") \
|
|
|
|
V(constructor_symbol, "constructor") \
|
|
|
|
V(code_symbol, ".code") \
|
|
|
|
V(result_symbol, ".result") \
|
|
|
|
V(catch_var_symbol, ".catch-var") \
|
|
|
|
V(empty_symbol, "") \
|
|
|
|
V(eval_symbol, "eval") \
|
|
|
|
V(function_symbol, "function") \
|
|
|
|
V(length_symbol, "length") \
|
|
|
|
V(name_symbol, "name") \
|
|
|
|
V(number_symbol, "number") \
|
2008-10-17 11:33:04 +00:00
|
|
|
V(Number_symbol, "Number") \
|
|
|
|
V(RegExp_symbol, "RegExp") \
|
2008-07-03 15:10:15 +00:00
|
|
|
V(object_symbol, "object") \
|
|
|
|
V(prototype_symbol, "prototype") \
|
|
|
|
V(string_symbol, "string") \
|
2008-10-07 10:54:50 +00:00
|
|
|
V(String_symbol, "String") \
|
|
|
|
V(Date_symbol, "Date") \
|
2008-07-03 15:10:15 +00:00
|
|
|
V(this_symbol, "this") \
|
|
|
|
V(to_string_symbol, "toString") \
|
|
|
|
V(char_at_symbol, "CharAt") \
|
|
|
|
V(undefined_symbol, "undefined") \
|
|
|
|
V(value_of_symbol, "valueOf") \
|
|
|
|
V(CreateObjectLiteralBoilerplate_symbol, "CreateObjectLiteralBoilerplate") \
|
|
|
|
V(CreateArrayLiteral_symbol, "CreateArrayLiteral") \
|
|
|
|
V(InitializeVarGlobal_symbol, "InitializeVarGlobal") \
|
|
|
|
V(InitializeConstGlobal_symbol, "InitializeConstGlobal") \
|
|
|
|
V(stack_overflow_symbol, "kStackOverflowBoilerplate") \
|
|
|
|
V(illegal_access_symbol, "illegal access") \
|
|
|
|
V(out_of_memory_symbol, "out-of-memory") \
|
|
|
|
V(illegal_execution_state_symbol, "illegal execution state") \
|
|
|
|
V(get_symbol, "get") \
|
|
|
|
V(set_symbol, "set") \
|
|
|
|
V(function_class_symbol, "Function") \
|
|
|
|
V(illegal_argument_symbol, "illegal argument") \
|
|
|
|
V(MakeReferenceError_symbol, "MakeReferenceError") \
|
|
|
|
V(MakeSyntaxError_symbol, "MakeSyntaxError") \
|
|
|
|
V(MakeTypeError_symbol, "MakeTypeError") \
|
|
|
|
V(invalid_lhs_in_assignment_symbol, "invalid_lhs_in_assignment") \
|
|
|
|
V(invalid_lhs_in_for_in_symbol, "invalid_lhs_in_for_in") \
|
|
|
|
V(invalid_lhs_in_postfix_op_symbol, "invalid_lhs_in_postfix_op") \
|
|
|
|
V(invalid_lhs_in_prefix_op_symbol, "invalid_lhs_in_prefix_op") \
|
|
|
|
V(illegal_return_symbol, "illegal_return") \
|
|
|
|
V(illegal_break_symbol, "illegal_break") \
|
|
|
|
V(illegal_continue_symbol, "illegal_continue") \
|
|
|
|
V(unknown_label_symbol, "unknown_label") \
|
|
|
|
V(redeclaration_symbol, "redeclaration") \
|
|
|
|
V(failure_symbol, "<failure>") \
|
|
|
|
V(space_symbol, " ") \
|
|
|
|
V(exec_symbol, "exec") \
|
|
|
|
V(zero_symbol, "0")
|
|
|
|
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// Forward declaration of the GCTracer class.
|
|
|
|
class GCTracer;
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// The all static Heap captures the interface to the global object heap.
|
|
|
|
// All JavaScript contexts by this process share the same object heap.
|
|
|
|
|
|
|
|
class Heap : public AllStatic {
|
|
|
|
public:
|
|
|
|
// Configure heap size before setup. Return false if the heap has been
|
|
|
|
// setup already.
|
|
|
|
static bool ConfigureHeap(int semispace_size, int old_gen_size);
|
2008-07-30 08:49:36 +00:00
|
|
|
static bool ConfigureHeapDefault();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Initializes the global object heap. If create_heap_objects is true,
|
|
|
|
// also creates the basic non-mutable objects.
|
|
|
|
// Returns whether it succeeded.
|
|
|
|
static bool Setup(bool create_heap_objects);
|
|
|
|
|
|
|
|
// Destroys all memory allocated by the heap.
|
|
|
|
static void TearDown();
|
|
|
|
|
|
|
|
// Returns whether Setup has been called.
|
|
|
|
static bool HasBeenSetup();
|
|
|
|
|
|
|
|
// Returns the maximum heap capacity.
|
|
|
|
static int MaxCapacity() {
|
|
|
|
return young_generation_size_ + old_generation_size_;
|
|
|
|
}
|
|
|
|
static int SemiSpaceSize() { return semispace_size_; }
|
|
|
|
static int InitialSemiSpaceSize() { return initial_semispace_size_; }
|
|
|
|
static int YoungGenerationSize() { return young_generation_size_; }
|
|
|
|
static int OldGenerationSize() { return old_generation_size_; }
|
|
|
|
|
|
|
|
// Returns the capacity of the heap in bytes w/o growing. Heap grows when
|
|
|
|
// more spaces are needed until it reaches the limit.
|
|
|
|
static int Capacity();
|
|
|
|
|
|
|
|
// Returns the available bytes in space w/o growing.
|
|
|
|
// Heap doesn't guarantee that it can allocate an object that requires
|
|
|
|
// all available bytes. Check MaxHeapObjectSize() instead.
|
|
|
|
static int Available();
|
|
|
|
|
|
|
|
// Returns the maximum object size that heap supports. Objects larger than
|
|
|
|
// the maximum heap object size are allocated in a large object space.
|
|
|
|
static inline int MaxHeapObjectSize();
|
|
|
|
|
|
|
|
// Returns of size of all objects residing in the heap.
|
|
|
|
static int SizeOfObjects();
|
|
|
|
|
|
|
|
// Return the starting address and a mask for the new space. And-masking an
|
|
|
|
// address with the mask will result in the start address of the new space
|
|
|
|
// for all addresses in either semispace.
|
2008-10-17 09:13:27 +00:00
|
|
|
static Address NewSpaceStart() { return new_space_.start(); }
|
|
|
|
static uint32_t NewSpaceMask() { return new_space_.mask(); }
|
|
|
|
static Address NewSpaceTop() { return new_space_.top(); }
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2008-10-17 09:13:27 +00:00
|
|
|
static NewSpace* new_space() { return &new_space_; }
|
2008-09-05 12:34:09 +00:00
|
|
|
static OldSpace* old_pointer_space() { return old_pointer_space_; }
|
|
|
|
static OldSpace* old_data_space() { return old_data_space_; }
|
2008-07-03 15:10:15 +00:00
|
|
|
static OldSpace* code_space() { return code_space_; }
|
|
|
|
static MapSpace* map_space() { return map_space_; }
|
|
|
|
static LargeObjectSpace* lo_space() { return lo_space_; }
|
|
|
|
|
|
|
|
static Address* NewSpaceAllocationTopAddress() {
|
2008-10-17 09:13:27 +00:00
|
|
|
return new_space_.allocation_top_address();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
static Address* NewSpaceAllocationLimitAddress() {
|
2008-10-17 09:13:27 +00:00
|
|
|
return new_space_.allocation_limit_address();
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Allocates and initializes a new JavaScript object based on a
|
|
|
|
// constructor.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateJSObject(JSFunction* constructor,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
2008-10-22 08:21:18 +00:00
|
|
|
// Returns a deep copy of the JavaScript object.
|
|
|
|
// Properties and elements are copied too.
|
|
|
|
// Returns failure if allocation failed.
|
|
|
|
static Object* CopyJSObject(JSObject* source);
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Allocates the function prototype.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateFunctionPrototype(JSFunction* function);
|
|
|
|
|
Split window support from V8.
Here is a description of the background and design of split window in Chrome and V8:
https://docs.google.com/a/google.com/Doc?id=chhjkpg_47fwddxbfr
This change list splits the window object into two parts: 1) an inner window object used as the global object of contexts; 2) an outer window object exposed to JavaScript and accessible by the name 'window'. Firefox did it awhile ago, here are some discussions: https://wiki.mozilla.org/Gecko:SplitWindow. One additional benefit of splitting window in Chrome is that accessing global variables don't need security checks anymore, it can improve applications that use many global variables.
V8 support of split window:
There are a small number of changes on V8 api to support split window:
Security context is removed from V8, so does related API functions;
A global object can be detached from its context and reused by a new context;
Access checks on an object template can be turned on/off by default;
An object can turn on its access checks later;
V8 has a new object type, ApiGlobalObject, which is the outer window object type. The existing JSGlobalObject becomes the inner window object type. Security checks are moved from JSGlobalObject to ApiGlobalObject. ApiGlobalObject is the one exposed to JavaScript, it is accessible through Context::Global(). ApiGlobalObject's prototype is set to JSGlobalObject so that property lookups are forwarded to JSGlobalObject. ApiGlobalObject forwards all other property access requests to JSGlobalObject, such as SetProperty, DeleteProperty, etc.
Security token is moved to a global context, and ApiGlobalObject has a reference to its global context. JSGlobalObject has a reference to its global context as well. When accessing properties on a global object in JavaScript, the domain security check is performed by comparing the security token of the lexical context (Top::global_context()) to the token of global object's context. The check is only needed when the receiver is a window object, such as 'window.document'. Accessing global variables, such as 'var foo = 3; foo' does not need checks because the receiver is the inner window object.
When an outer window is detached from its global context (when a frame navigates away from a page), it is completely detached from the inner window. A new context is created for the new page, and the outer global object is reused. At this point, the access check on the DOMWindow wrapper of the old context is turned on. The code in old context is still able to access DOMWindow properties, but it has to go through domain security checks.
It is debatable on how to implement the outer window object. Currently each property access function has to check if the receiver is ApiGlobalObject type. This approach might be error-prone that one may forget to check the receiver when adding new functions. It is unlikely a performance issue because accessing global variables are more common than 'window.foo' style coding.
I am still working on the ARM port, and I'd like to hear comments and suggestions on the best way to support it in V8.
Review URL: http://codereview.chromium.org/7366
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@540 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2008-10-21 19:07:58 +00:00
|
|
|
// Reinitialize an JSGlobalProxy based on a constructor. The object
|
2008-07-03 15:10:15 +00:00
|
|
|
// must have the same size as objects allocated using the
|
Split window support from V8.
Here is a description of the background and design of split window in Chrome and V8:
https://docs.google.com/a/google.com/Doc?id=chhjkpg_47fwddxbfr
This change list splits the window object into two parts: 1) an inner window object used as the global object of contexts; 2) an outer window object exposed to JavaScript and accessible by the name 'window'. Firefox did it awhile ago, here are some discussions: https://wiki.mozilla.org/Gecko:SplitWindow. One additional benefit of splitting window in Chrome is that accessing global variables don't need security checks anymore, it can improve applications that use many global variables.
V8 support of split window:
There are a small number of changes on V8 api to support split window:
Security context is removed from V8, so does related API functions;
A global object can be detached from its context and reused by a new context;
Access checks on an object template can be turned on/off by default;
An object can turn on its access checks later;
V8 has a new object type, ApiGlobalObject, which is the outer window object type. The existing JSGlobalObject becomes the inner window object type. Security checks are moved from JSGlobalObject to ApiGlobalObject. ApiGlobalObject is the one exposed to JavaScript, it is accessible through Context::Global(). ApiGlobalObject's prototype is set to JSGlobalObject so that property lookups are forwarded to JSGlobalObject. ApiGlobalObject forwards all other property access requests to JSGlobalObject, such as SetProperty, DeleteProperty, etc.
Security token is moved to a global context, and ApiGlobalObject has a reference to its global context. JSGlobalObject has a reference to its global context as well. When accessing properties on a global object in JavaScript, the domain security check is performed by comparing the security token of the lexical context (Top::global_context()) to the token of global object's context. The check is only needed when the receiver is a window object, such as 'window.document'. Accessing global variables, such as 'var foo = 3; foo' does not need checks because the receiver is the inner window object.
When an outer window is detached from its global context (when a frame navigates away from a page), it is completely detached from the inner window. A new context is created for the new page, and the outer global object is reused. At this point, the access check on the DOMWindow wrapper of the old context is turned on. The code in old context is still able to access DOMWindow properties, but it has to go through domain security checks.
It is debatable on how to implement the outer window object. Currently each property access function has to check if the receiver is ApiGlobalObject type. This approach might be error-prone that one may forget to check the receiver when adding new functions. It is unlikely a performance issue because accessing global variables are more common than 'window.foo' style coding.
I am still working on the ARM port, and I'd like to hear comments and suggestions on the best way to support it in V8.
Review URL: http://codereview.chromium.org/7366
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@540 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2008-10-21 19:07:58 +00:00
|
|
|
// constructor. The object is reinitialized and behaves as an
|
2008-07-03 15:10:15 +00:00
|
|
|
// object that has been freshly allocated using the constructor.
|
Split window support from V8.
Here is a description of the background and design of split window in Chrome and V8:
https://docs.google.com/a/google.com/Doc?id=chhjkpg_47fwddxbfr
This change list splits the window object into two parts: 1) an inner window object used as the global object of contexts; 2) an outer window object exposed to JavaScript and accessible by the name 'window'. Firefox did it awhile ago, here are some discussions: https://wiki.mozilla.org/Gecko:SplitWindow. One additional benefit of splitting window in Chrome is that accessing global variables don't need security checks anymore, it can improve applications that use many global variables.
V8 support of split window:
There are a small number of changes on V8 api to support split window:
Security context is removed from V8, so does related API functions;
A global object can be detached from its context and reused by a new context;
Access checks on an object template can be turned on/off by default;
An object can turn on its access checks later;
V8 has a new object type, ApiGlobalObject, which is the outer window object type. The existing JSGlobalObject becomes the inner window object type. Security checks are moved from JSGlobalObject to ApiGlobalObject. ApiGlobalObject is the one exposed to JavaScript, it is accessible through Context::Global(). ApiGlobalObject's prototype is set to JSGlobalObject so that property lookups are forwarded to JSGlobalObject. ApiGlobalObject forwards all other property access requests to JSGlobalObject, such as SetProperty, DeleteProperty, etc.
Security token is moved to a global context, and ApiGlobalObject has a reference to its global context. JSGlobalObject has a reference to its global context as well. When accessing properties on a global object in JavaScript, the domain security check is performed by comparing the security token of the lexical context (Top::global_context()) to the token of global object's context. The check is only needed when the receiver is a window object, such as 'window.document'. Accessing global variables, such as 'var foo = 3; foo' does not need checks because the receiver is the inner window object.
When an outer window is detached from its global context (when a frame navigates away from a page), it is completely detached from the inner window. A new context is created for the new page, and the outer global object is reused. At this point, the access check on the DOMWindow wrapper of the old context is turned on. The code in old context is still able to access DOMWindow properties, but it has to go through domain security checks.
It is debatable on how to implement the outer window object. Currently each property access function has to check if the receiver is ApiGlobalObject type. This approach might be error-prone that one may forget to check the receiver when adding new functions. It is unlikely a performance issue because accessing global variables are more common than 'window.foo' style coding.
I am still working on the ARM port, and I'd like to hear comments and suggestions on the best way to support it in V8.
Review URL: http://codereview.chromium.org/7366
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@540 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2008-10-21 19:07:58 +00:00
|
|
|
static Object* ReinitializeJSGlobalProxy(JSFunction* constructor,
|
|
|
|
JSGlobalProxy* global);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Allocates and initializes a new JavaScript object based on a map.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateJSObjectFromMap(Map* map,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
|
|
|
// Allocates a heap object based on the map.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
|
|
|
static Object* Allocate(Map* map, AllocationSpace space);
|
|
|
|
|
|
|
|
// Allocates a JS Map in the heap.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
|
|
|
static Object* AllocateMap(InstanceType instance_type, int instance_size);
|
|
|
|
|
|
|
|
// Allocates a partial map for bootstrapping.
|
|
|
|
static Object* AllocatePartialMap(InstanceType instance_type,
|
|
|
|
int instance_size);
|
|
|
|
|
|
|
|
// Allocate a map for the specified function
|
|
|
|
static Object* AllocateInitialMap(JSFunction* fun);
|
|
|
|
|
|
|
|
// Allocates and fully initializes a String. There are two String
|
|
|
|
// encodings: ASCII and two byte. One should choose between the three string
|
|
|
|
// allocation functions based on the encoding of the string buffer used to
|
|
|
|
// initialized the string.
|
|
|
|
// - ...FromAscii initializes the string from a buffer that is ASCII
|
|
|
|
// encoded (it does not check that the buffer is ASCII encoded) and the
|
|
|
|
// result will be ASCII encoded.
|
|
|
|
// - ...FromUTF8 initializes the string from a buffer that is UTF-8
|
|
|
|
// encoded. If the characters are all single-byte characters, the
|
|
|
|
// result will be ASCII encoded, otherwise it will converted to two
|
|
|
|
// byte.
|
|
|
|
// - ...FromTwoByte initializes the string from a buffer that is two-byte
|
|
|
|
// encoded. If the characters are all single-byte characters, the
|
|
|
|
// result will be converted to ASCII, otherwise it will be left as
|
|
|
|
// two-byte.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateStringFromAscii(
|
|
|
|
Vector<const char> str,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
static Object* AllocateStringFromUtf8(
|
|
|
|
Vector<const char> str,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
static Object* AllocateStringFromTwoByte(
|
|
|
|
Vector<const uc16> str,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
|
|
|
// Allocates a symbol in old space based on the character stream.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
|
|
|
static Object* AllocateSymbol(unibrow::CharacterStream* buffer,
|
|
|
|
int chars,
|
2008-10-06 09:35:52 +00:00
|
|
|
uint32_t length_field);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Allocates and partially initializes a String. There are two String
|
|
|
|
// encodings: ASCII and two byte. These functions allocate a string of the
|
|
|
|
// given length and set its map and length fields. The characters of the
|
|
|
|
// string are uninitialized.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateRawAsciiString(
|
|
|
|
int length,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
static Object* AllocateRawTwoByteString(
|
|
|
|
int length,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
|
|
|
// Computes a single character string where the character has code.
|
|
|
|
// A cache is used for ascii codes.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed. Please note this does not perform a garbage collection.
|
|
|
|
static Object* LookupSingleCharacterStringFromCode(uint16_t code);
|
|
|
|
|
|
|
|
// Allocate a byte array of the specified length
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please not this does not perform a garbage collection.
|
|
|
|
static Object* AllocateByteArray(int length);
|
|
|
|
|
|
|
|
// Allocates a fixed array initialized with undefined values
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
2008-10-20 06:35:28 +00:00
|
|
|
static Object* AllocateFixedArray(int length, PretenureFlag pretenure);
|
|
|
|
// Allocate uninitialized, non-tenured fixed array with length elements.
|
|
|
|
static Object* AllocateFixedArray(int length);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2008-10-20 06:35:28 +00:00
|
|
|
// Make a copy of src and return it. Returns
|
|
|
|
// Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
|
|
|
|
static Object* CopyFixedArray(FixedArray* src);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Allocates a fixed array initialized with the hole values.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateFixedArrayWithHoles(int length);
|
|
|
|
|
|
|
|
// AllocateHashTable is identical to AllocateFixedArray except
|
|
|
|
// that the resulting object has hash_table_map as map.
|
|
|
|
static Object* AllocateHashTable(int length);
|
|
|
|
|
|
|
|
// Allocate a global (but otherwise uninitialized) context.
|
|
|
|
static Object* AllocateGlobalContext();
|
|
|
|
|
|
|
|
// Allocate a function context.
|
|
|
|
static Object* AllocateFunctionContext(int length, JSFunction* closure);
|
|
|
|
|
|
|
|
// Allocate a 'with' context.
|
|
|
|
static Object* AllocateWithContext(Context* previous, JSObject* extension);
|
|
|
|
|
|
|
|
// Allocates a new utility object in the old generation.
|
|
|
|
static Object* AllocateStruct(InstanceType type);
|
|
|
|
|
|
|
|
|
|
|
|
// Initializes a function with a shared part and prototype.
|
|
|
|
// Returns the function.
|
|
|
|
// Note: this code was factored out of AllocateFunction such that
|
|
|
|
// other parts of the VM could use it. Specifically, a function that creates
|
|
|
|
// instances of type JS_FUNCTION_TYPE benefit from the use of this function.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* InitializeFunction(JSFunction* function,
|
|
|
|
SharedFunctionInfo* shared,
|
|
|
|
Object* prototype);
|
|
|
|
|
|
|
|
// Allocates a function initialized with a shared part.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateFunction(Map* function_map,
|
|
|
|
SharedFunctionInfo* shared,
|
|
|
|
Object* prototype);
|
|
|
|
|
|
|
|
// Indicies for direct access into argument objects.
|
|
|
|
static const int arguments_callee_index = 0;
|
|
|
|
static const int arguments_length_index = 1;
|
|
|
|
|
|
|
|
// Allocates an arguments object - optionally with an elements array.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateArgumentsObject(Object* callee, int length);
|
|
|
|
|
|
|
|
// Converts a double into either a Smi or a HeapNumber object.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* NewNumberFromDouble(double value,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
|
|
|
// Same as NewNumberFromDouble, but may return a preallocated/immutable
|
|
|
|
// number object (e.g., minus_zero_value_, nan_value_)
|
|
|
|
static Object* NumberFromDouble(double value,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
|
|
|
// Allocated a HeapNumber from value.
|
|
|
|
static Object* AllocateHeapNumber(double value, PretenureFlag pretenure);
|
|
|
|
static Object* AllocateHeapNumber(double value); // pretenure = NOT_TENURED
|
|
|
|
|
|
|
|
// Converts an int into either a Smi or a HeapNumber object.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static inline Object* NumberFromInt32(int32_t value);
|
|
|
|
|
|
|
|
// Converts an int into either a Smi or a HeapNumber object.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static inline Object* NumberFromUint32(uint32_t value);
|
|
|
|
|
|
|
|
// Allocates a new proxy object.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateProxy(Address proxy,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
|
|
|
// Allocates a new SharedFunctionInfo object.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateSharedFunctionInfo(Object* name);
|
|
|
|
|
|
|
|
// Allocates a new cons string object.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateConsString(String* first, String* second);
|
|
|
|
|
|
|
|
// Allocates a new sliced string object which is a slice of an underlying
|
|
|
|
// string buffer stretching from the index start (inclusive) to the index
|
|
|
|
// end (exclusive).
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateSlicedString(String* buffer, int start, int end);
|
|
|
|
|
|
|
|
// Allocates a new sub string object which is a substring of an underlying
|
|
|
|
// string buffer stretching from the index start (inclusive) to the index
|
|
|
|
// end (exclusive).
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateSubString(String* buffer, int start, int end);
|
|
|
|
|
|
|
|
// Allocate a new external string object, which is backed by a string
|
|
|
|
// resource that resides outside the V8 heap.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this does not perform a garbage collection.
|
|
|
|
static Object* AllocateExternalStringFromAscii(
|
|
|
|
ExternalAsciiString::Resource* resource);
|
|
|
|
static Object* AllocateExternalStringFromTwoByte(
|
|
|
|
ExternalTwoByteString::Resource* resource);
|
|
|
|
|
2008-09-05 12:34:09 +00:00
|
|
|
// Allocates an uninitialized object. The memory is non-executable if the
|
|
|
|
// hardware and OS allow.
|
2008-07-03 15:10:15 +00:00
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
2008-09-05 12:34:09 +00:00
|
|
|
static inline Object* AllocateRaw(int size_in_bytes,
|
|
|
|
AllocationSpace space);
|
2008-07-30 08:49:36 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Makes a new native code object
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
|
|
|
static Object* CreateCode(const CodeDesc& desc,
|
|
|
|
ScopeInfo<>* sinfo,
|
|
|
|
Code::Flags flags);
|
|
|
|
|
|
|
|
static Object* CopyCode(Code* code);
|
|
|
|
// Finds the symbol for string in the symbol table.
|
|
|
|
// If not found, a new symbol is added to the table and returned.
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
|
|
|
static Object* LookupSymbol(Vector<const char> str);
|
|
|
|
static Object* LookupAsciiSymbol(const char* str) {
|
|
|
|
return LookupSymbol(CStrVector(str));
|
|
|
|
}
|
|
|
|
static Object* LookupSymbol(String* str);
|
2008-10-07 10:10:03 +00:00
|
|
|
static bool LookupSymbolIfExists(String* str, String** symbol);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Compute the matching symbol map for a string if possible.
|
|
|
|
// NULL is returned if string is in new space or not flattened.
|
|
|
|
static Map* SymbolMapForString(String* str);
|
|
|
|
|
|
|
|
// Converts the given boolean condition to JavaScript boolean value.
|
|
|
|
static Object* ToBoolean(bool condition) {
|
|
|
|
return condition ? true_value() : false_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Code that should be run before and after each GC. Includes some
|
|
|
|
// reporting/verification activities when compiled with DEBUG set.
|
|
|
|
static void GarbageCollectionPrologue();
|
|
|
|
static void GarbageCollectionEpilogue();
|
|
|
|
|
|
|
|
// Performs garbage collection operation.
|
|
|
|
// Returns whether required_space bytes are available after the collection.
|
|
|
|
static bool CollectGarbage(int required_space, AllocationSpace space);
|
|
|
|
|
2008-09-05 12:34:09 +00:00
|
|
|
// Performs a full garbage collection.
|
|
|
|
static void CollectAllGarbage();
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Utility to invoke the scavenger. This is needed in test code to
|
|
|
|
// ensure correct callback for weak global handles.
|
2008-07-30 08:49:36 +00:00
|
|
|
static void PerformScavenge();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2008-10-20 07:37:51 +00:00
|
|
|
#ifdef DEBUG
|
2008-10-20 07:31:33 +00:00
|
|
|
// Utility used with flag gc-greedy.
|
|
|
|
static bool GarbageCollectionGreedyCheck();
|
2008-10-20 07:37:51 +00:00
|
|
|
#endif
|
2008-10-20 07:31:33 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
static void SetGlobalGCPrologueCallback(GCCallback callback) {
|
|
|
|
global_gc_prologue_callback_ = callback;
|
|
|
|
}
|
|
|
|
static void SetGlobalGCEpilogueCallback(GCCallback callback) {
|
|
|
|
global_gc_epilogue_callback_ = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Heap roots
|
|
|
|
#define ROOT_ACCESSOR(type, name) static type* name() { return name##_; }
|
|
|
|
ROOT_LIST(ROOT_ACCESSOR)
|
|
|
|
#undef ROOT_ACCESSOR
|
|
|
|
|
|
|
|
// Utility type maps
|
|
|
|
#define STRUCT_MAP_ACCESSOR(NAME, Name, name) \
|
|
|
|
static Map* name##_map() { return name##_map_; }
|
|
|
|
STRUCT_LIST(STRUCT_MAP_ACCESSOR)
|
|
|
|
#undef STRUCT_MAP_ACCESSOR
|
|
|
|
|
|
|
|
#define SYMBOL_ACCESSOR(name, str) static String* name() { return name##_; }
|
|
|
|
SYMBOL_LIST(SYMBOL_ACCESSOR)
|
|
|
|
#undef SYMBOL_ACCESSOR
|
|
|
|
|
|
|
|
// Iterates over all roots in the heap.
|
|
|
|
static void IterateRoots(ObjectVisitor* v);
|
|
|
|
// Iterates over all strong roots in the heap.
|
|
|
|
static void IterateStrongRoots(ObjectVisitor* v);
|
|
|
|
|
|
|
|
// Iterates remembered set of an old space.
|
|
|
|
static void IterateRSet(PagedSpace* space, ObjectSlotCallback callback);
|
|
|
|
|
|
|
|
// Iterates a range of remembered set addresses starting with rset_start
|
|
|
|
// corresponding to the range of allocated pointers
|
|
|
|
// [object_start, object_end).
|
|
|
|
static void IterateRSetRange(Address object_start,
|
|
|
|
Address object_end,
|
|
|
|
Address rset_start,
|
|
|
|
ObjectSlotCallback copy_object_func);
|
|
|
|
|
|
|
|
// Returns whether the object resides in new space.
|
|
|
|
static inline bool InNewSpace(Object* object);
|
|
|
|
static inline bool InFromSpace(Object* object);
|
|
|
|
static inline bool InToSpace(Object* object);
|
|
|
|
|
|
|
|
// Checks whether an address/object in the heap (including auxiliary
|
|
|
|
// area and unused area).
|
|
|
|
static bool Contains(Address addr);
|
|
|
|
static bool Contains(HeapObject* value);
|
|
|
|
|
|
|
|
// Checks whether an address/object in a space.
|
|
|
|
// Currently used by tests and heap verification only.
|
|
|
|
static bool InSpace(Address addr, AllocationSpace space);
|
|
|
|
static bool InSpace(HeapObject* value, AllocationSpace space);
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// Finds out which space an object should get promoted to based on its type.
|
2008-09-05 12:34:09 +00:00
|
|
|
static inline OldSpace* TargetSpace(HeapObject* object);
|
2008-07-30 08:49:36 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Sets the stub_cache_ (only used when expanding the dictionary).
|
|
|
|
static void set_code_stubs(Dictionary* value) { code_stubs_ = value; }
|
|
|
|
|
|
|
|
// Sets the non_monomorphic_cache_ (only used when expanding the dictionary).
|
|
|
|
static void set_non_monomorphic_cache(Dictionary* value) {
|
|
|
|
non_monomorphic_cache_ = value;
|
|
|
|
}
|
|
|
|
|
2008-10-23 07:04:56 +00:00
|
|
|
// Gets, sets and clears the lookup cache used for keyed access.
|
|
|
|
static inline Object* GetKeyedLookupCache();
|
|
|
|
static inline void SetKeyedLookupCache(LookupCache* cache);
|
|
|
|
static inline void ClearKeyedLookupCache();
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
static void Print();
|
|
|
|
static void PrintHandles();
|
|
|
|
|
|
|
|
// Verify the heap is in its normal state before or after a GC.
|
|
|
|
static void Verify();
|
|
|
|
|
|
|
|
// Report heap statistics.
|
|
|
|
static void ReportHeapStatistics(const char* title);
|
|
|
|
static void ReportCodeStatistics(const char* title);
|
|
|
|
|
|
|
|
// Fill in bogus values in from space
|
|
|
|
static void ZapFromSpace();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Makes a new symbol object
|
|
|
|
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
|
|
|
// failed.
|
|
|
|
// Please note this function does not perform a garbage collection.
|
|
|
|
static Object* CreateSymbol(const char* str, int length, int hash);
|
|
|
|
static Object* CreateSymbol(String* str);
|
|
|
|
|
|
|
|
// Write barrier support for address[offset] = o.
|
|
|
|
inline static void RecordWrite(Address address, int offset);
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// Given an address occupied by a live code object, return that object.
|
2008-07-03 15:10:15 +00:00
|
|
|
static Object* FindCodeObject(Address a);
|
|
|
|
|
|
|
|
// Invoke Shrink on shrinkable spaces.
|
|
|
|
static void Shrink();
|
|
|
|
|
|
|
|
enum HeapState { NOT_IN_GC, SCAVENGE, MARK_COMPACT };
|
|
|
|
static inline HeapState gc_state() { return gc_state_; }
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
static bool IsAllocationAllowed() { return allocation_allowed_; }
|
|
|
|
static inline bool allow_allocation(bool enable);
|
|
|
|
|
|
|
|
static bool disallow_allocation_failure() {
|
|
|
|
return disallow_allocation_failure_;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TracePathToObject();
|
|
|
|
static void TracePathToGlobal();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Callback function pased to Heap::Iterate etc. Copies an object if
|
|
|
|
// necessary, the object might be promoted to an old space. The caller must
|
|
|
|
// ensure the precondition that the object is (a) a heap object and (b) in
|
|
|
|
// the heap's from space.
|
2008-10-21 08:48:11 +00:00
|
|
|
static void ScavengePointer(HeapObject** p);
|
|
|
|
static inline void ScavengeObject(HeapObject** p, HeapObject* object);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Clear a range of remembered set addresses corresponding to the object
|
|
|
|
// area address 'start' with size 'size_in_bytes', eg, when adding blocks
|
|
|
|
// to the free list.
|
|
|
|
static void ClearRSetRange(Address start, int size_in_bytes);
|
|
|
|
|
|
|
|
// Rebuild remembered set in old and map spaces.
|
|
|
|
static void RebuildRSets();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Support for the API.
|
|
|
|
//
|
|
|
|
|
|
|
|
static bool CreateApiObjects();
|
|
|
|
|
|
|
|
// Attempt to find the number in a small cache. If we finds it, return
|
|
|
|
// the string representation of the number. Otherwise return undefined.
|
|
|
|
static Object* GetNumberStringCache(Object* number);
|
|
|
|
|
|
|
|
// Update the cache with a new number-string pair.
|
|
|
|
static void SetNumberStringCache(Object* number, String* str);
|
|
|
|
|
|
|
|
// Entries in the cache. Must be a power of 2.
|
|
|
|
static const int kNumberStringCacheSize = 64;
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// Adjusts the amount of registered external memory.
|
|
|
|
// Returns the adjusted value.
|
|
|
|
static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
|
|
|
|
int amount = amount_of_external_allocated_memory_ + change_in_bytes;
|
|
|
|
if (change_in_bytes >= 0) {
|
|
|
|
// Avoid overflow.
|
|
|
|
if (amount > amount_of_external_allocated_memory_) {
|
|
|
|
amount_of_external_allocated_memory_ = amount;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Avoid underflow.
|
|
|
|
if (amount >= 0) {
|
|
|
|
amount_of_external_allocated_memory_ = amount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ASSERT(amount_of_external_allocated_memory_ >= 0);
|
|
|
|
return amount_of_external_allocated_memory_;
|
|
|
|
}
|
|
|
|
|
2008-10-23 14:55:45 +00:00
|
|
|
// Allocate unitialized fixed array (pretenure == NON_TENURE).
|
|
|
|
static Object* AllocateRawFixedArray(int length);
|
|
|
|
|
2008-10-29 09:27:59 +00:00
|
|
|
// True if we have reached the allocation limit in the old generation that
|
|
|
|
// should force the next GC (caused normally) to be a full one.
|
|
|
|
static bool OldGenerationPromotionLimitReached() {
|
|
|
|
return (PromotedSpaceSize() + PromotedExternalMemorySize())
|
|
|
|
> old_gen_promotion_limit_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// True if we have reached the allocation limit in the old generation that
|
|
|
|
// should artificially cause a GC right now.
|
|
|
|
static bool OldGenerationAllocationLimitReached() {
|
|
|
|
return (PromotedSpaceSize() + PromotedExternalMemorySize())
|
|
|
|
> old_gen_allocation_limit_;
|
|
|
|
}
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
private:
|
|
|
|
static int semispace_size_;
|
|
|
|
static int initial_semispace_size_;
|
|
|
|
static int young_generation_size_;
|
|
|
|
static int old_generation_size_;
|
|
|
|
|
|
|
|
static int new_space_growth_limit_;
|
|
|
|
static int scavenge_count_;
|
|
|
|
|
|
|
|
static const int kMaxMapSpaceSize = 8*MB;
|
|
|
|
|
2008-10-17 09:13:27 +00:00
|
|
|
static NewSpace new_space_;
|
2008-09-05 12:34:09 +00:00
|
|
|
static OldSpace* old_pointer_space_;
|
|
|
|
static OldSpace* old_data_space_;
|
2008-07-03 15:10:15 +00:00
|
|
|
static OldSpace* code_space_;
|
|
|
|
static MapSpace* map_space_;
|
|
|
|
static LargeObjectSpace* lo_space_;
|
|
|
|
static HeapState gc_state_;
|
|
|
|
|
|
|
|
// Returns the size of object residing in non new spaces.
|
|
|
|
static int PromotedSpaceSize();
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// Returns the amount of external memory registered since last global gc.
|
|
|
|
static int PromotedExternalMemorySize();
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
static int mc_count_; // how many mark-compact collections happened
|
|
|
|
static int gc_count_; // how many gc happened
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
static bool allocation_allowed_;
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// If the --gc-interval flag is set to a positive value, this
|
|
|
|
// variable holds the value indicating the number of allocations
|
|
|
|
// remain until the next failure and garbage collection.
|
|
|
|
static int allocation_timeout_;
|
|
|
|
|
|
|
|
// Do we expect to be able to handle allocation failure at this
|
|
|
|
// time?
|
|
|
|
static bool disallow_allocation_failure_;
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2008-10-29 09:27:59 +00:00
|
|
|
// Limit that triggers a global GC on the next (normally caused) GC. This
|
|
|
|
// is checked when we have already decided to do a GC to help determine
|
|
|
|
// which collector to invoke.
|
|
|
|
static int old_gen_promotion_limit_;
|
|
|
|
|
|
|
|
// Limit that triggers a global GC as soon as is reasonable. This is
|
|
|
|
// checked before expanding a paged space in the old generation and on
|
|
|
|
// every allocation in large object space.
|
|
|
|
static int old_gen_allocation_limit_;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// The amount of external memory registered through the API kept alive
|
|
|
|
// by global handles
|
|
|
|
static int amount_of_external_allocated_memory_;
|
|
|
|
|
|
|
|
// Caches the amount of external memory registered at the last global gc.
|
|
|
|
static int amount_of_external_allocated_memory_at_last_global_gc_;
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Indicates that an allocation has failed in the old generation since the
|
|
|
|
// last GC.
|
|
|
|
static int old_gen_exhausted_;
|
|
|
|
|
|
|
|
// Declare all the roots
|
|
|
|
#define ROOT_DECLARATION(type, name) static type* name##_;
|
|
|
|
ROOT_LIST(ROOT_DECLARATION)
|
|
|
|
#undef ROOT_DECLARATION
|
|
|
|
|
|
|
|
// Utility type maps
|
|
|
|
#define DECLARE_STRUCT_MAP(NAME, Name, name) static Map* name##_map_;
|
|
|
|
STRUCT_LIST(DECLARE_STRUCT_MAP)
|
|
|
|
#undef DECLARE_STRUCT_MAP
|
|
|
|
|
|
|
|
#define SYMBOL_DECLARATION(name, str) static String* name##_;
|
|
|
|
SYMBOL_LIST(SYMBOL_DECLARATION)
|
|
|
|
#undef SYMBOL_DECLARATION
|
|
|
|
|
|
|
|
// GC callback function, called before and after mark-compact GC.
|
|
|
|
// Allocations in the callback function are disallowed.
|
|
|
|
static GCCallback global_gc_prologue_callback_;
|
|
|
|
static GCCallback global_gc_epilogue_callback_;
|
|
|
|
|
|
|
|
// Checks whether a global GC is necessary
|
|
|
|
static GarbageCollector SelectGarbageCollector(AllocationSpace space);
|
|
|
|
|
|
|
|
// Performs garbage collection
|
|
|
|
static void PerformGarbageCollection(AllocationSpace space,
|
2008-07-30 08:49:36 +00:00
|
|
|
GarbageCollector collector,
|
|
|
|
GCTracer* tracer);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Returns either a Smi or a Number object from 'value'. If 'new_object'
|
|
|
|
// is false, it may return a preallocated immutable object.
|
|
|
|
static Object* SmiOrNumberFromDouble(double value,
|
|
|
|
bool new_object,
|
|
|
|
PretenureFlag pretenure = NOT_TENURED);
|
|
|
|
|
2008-09-05 12:34:09 +00:00
|
|
|
// Allocate an uninitialized object in map space. The behavior is identical
|
|
|
|
// to Heap::AllocateRaw(size_in_bytes, MAP_SPACE), except that (a) it doesn't
|
|
|
|
// have to test the allocation space argument and (b) can reduce code size
|
|
|
|
// (since both AllocateRaw and AllocateRawMap are inlined).
|
2008-07-03 15:10:15 +00:00
|
|
|
static inline Object* AllocateRawMap(int size_in_bytes);
|
|
|
|
|
|
|
|
// Initializes a JSObject based on its map.
|
|
|
|
static void InitializeJSObjectFromMap(JSObject* obj,
|
|
|
|
FixedArray* properties,
|
|
|
|
Map* map);
|
|
|
|
|
|
|
|
static bool CreateInitialMaps();
|
|
|
|
static bool CreateInitialObjects();
|
|
|
|
static void CreateFixedStubs();
|
|
|
|
static Object* CreateOddball(Map* map,
|
|
|
|
const char* to_string,
|
|
|
|
Object* to_number);
|
|
|
|
|
|
|
|
// Allocate empty fixed array.
|
|
|
|
static Object* AllocateEmptyFixedArray();
|
|
|
|
|
|
|
|
// Performs a minor collection in new generation.
|
|
|
|
static void Scavenge();
|
|
|
|
|
|
|
|
// Performs a major collection in the whole heap.
|
2008-07-30 08:49:36 +00:00
|
|
|
static void MarkCompact(GCTracer* tracer);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Code to be run before and after mark-compact.
|
|
|
|
static void MarkCompactPrologue();
|
|
|
|
static void MarkCompactEpilogue();
|
|
|
|
|
|
|
|
// Helper function used by CopyObject to copy a source object to an
|
|
|
|
// allocated target object and update the forwarding pointer in the source
|
|
|
|
// object. Returns the target object.
|
2008-10-17 09:13:27 +00:00
|
|
|
static HeapObject* MigrateObject(HeapObject* source,
|
2008-07-03 15:10:15 +00:00
|
|
|
HeapObject* target,
|
|
|
|
int size);
|
|
|
|
|
|
|
|
// Helper function that governs the promotion policy from new space to
|
|
|
|
// old. If the object's old address lies below the new space's age
|
|
|
|
// mark or if we've already filled the bottom 1/16th of the to space,
|
|
|
|
// we try to promote this object.
|
|
|
|
static inline bool ShouldBePromoted(Address old_address, int object_size);
|
|
|
|
#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
|
|
|
|
// Record the copy of an object in the NewSpace's statistics.
|
|
|
|
static void RecordCopiedObject(HeapObject* obj);
|
|
|
|
|
|
|
|
// Record statistics before and after garbage collection.
|
|
|
|
static void ReportStatisticsBeforeGC();
|
|
|
|
static void ReportStatisticsAfterGC();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Update an old object's remembered set
|
|
|
|
static int UpdateRSet(HeapObject* obj);
|
|
|
|
|
|
|
|
// Rebuild remembered set in an old space.
|
|
|
|
static void RebuildRSets(PagedSpace* space);
|
|
|
|
|
|
|
|
// Rebuild remembered set in the large object space.
|
|
|
|
static void RebuildRSets(LargeObjectSpace* space);
|
|
|
|
|
2008-10-21 08:48:11 +00:00
|
|
|
// Slow part of scavenge object.
|
|
|
|
static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);
|
|
|
|
|
2008-10-22 08:21:18 +00:00
|
|
|
// Copy memory from src to dst.
|
|
|
|
inline static void CopyBlock(Object** dst, Object** src, int byte_size);
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
static const int kInitialSymbolTableSize = 2048;
|
2008-09-05 16:27:56 +00:00
|
|
|
static const int kInitialEvalCacheSize = 64;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
friend class Factory;
|
|
|
|
friend class DisallowAllocationFailure;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Visitor class to verify interior pointers that do not have remembered set
|
|
|
|
// bits. All heap object pointers have to point into the heap to a location
|
|
|
|
// that has a map pointer at its first word. Caveat: Heap::Contains is an
|
|
|
|
// approximation because it can return true for objects in a heap space but
|
|
|
|
// above the allocation pointer.
|
|
|
|
class VerifyPointersVisitor: public ObjectVisitor {
|
|
|
|
public:
|
|
|
|
void VisitPointers(Object** start, Object** end) {
|
|
|
|
for (Object** current = start; current < end; current++) {
|
|
|
|
if ((*current)->IsHeapObject()) {
|
|
|
|
HeapObject* object = HeapObject::cast(*current);
|
|
|
|
ASSERT(Heap::Contains(object));
|
|
|
|
ASSERT(object->map()->IsMap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Visitor class to verify interior pointers that have remembered set bits.
|
|
|
|
// As VerifyPointersVisitor but also checks that remembered set bits are
|
|
|
|
// always set for pointers into new space.
|
|
|
|
class VerifyPointersAndRSetVisitor: public ObjectVisitor {
|
|
|
|
public:
|
|
|
|
void VisitPointers(Object** start, Object** end) {
|
|
|
|
for (Object** current = start; current < end; current++) {
|
|
|
|
if ((*current)->IsHeapObject()) {
|
|
|
|
HeapObject* object = HeapObject::cast(*current);
|
|
|
|
ASSERT(Heap::Contains(object));
|
|
|
|
ASSERT(object->map()->IsMap());
|
|
|
|
if (Heap::InNewSpace(object)) {
|
|
|
|
ASSERT(Page::IsRSetSet(reinterpret_cast<Address>(current), 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2008-09-05 12:34:09 +00:00
|
|
|
// Space iterator for iterating over all spaces of the heap.
|
|
|
|
// Returns each space in turn, and null when it is done.
|
|
|
|
class AllSpaces BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
Space* next();
|
|
|
|
AllSpaces() { counter_ = FIRST_SPACE; }
|
|
|
|
private:
|
|
|
|
int counter_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Space iterator for iterating over all old spaces of the heap: Old pointer
|
|
|
|
// space, old data space and code space.
|
|
|
|
// Returns each space in turn, and null when it is done.
|
|
|
|
class OldSpaces BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
OldSpace* next();
|
|
|
|
OldSpaces() { counter_ = OLD_POINTER_SPACE; }
|
|
|
|
private:
|
|
|
|
int counter_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Space iterator for iterating over all the paged spaces of the heap:
|
|
|
|
// Map space, old pointer space, old data space and code space.
|
|
|
|
// Returns each space in turn, and null when it is done.
|
|
|
|
class PagedSpaces BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
PagedSpace* next();
|
|
|
|
PagedSpaces() { counter_ = OLD_POINTER_SPACE; }
|
|
|
|
private:
|
|
|
|
int counter_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// Space iterator for iterating over all spaces of the heap.
|
|
|
|
// For each space an object iterator is provided. The deallocation of the
|
|
|
|
// returned object iterators is handled by the space iterator.
|
|
|
|
class SpaceIterator : public Malloced {
|
|
|
|
public:
|
|
|
|
SpaceIterator();
|
|
|
|
virtual ~SpaceIterator();
|
|
|
|
|
|
|
|
bool has_next();
|
|
|
|
ObjectIterator* next();
|
|
|
|
|
|
|
|
private:
|
|
|
|
ObjectIterator* CreateIterator();
|
|
|
|
|
|
|
|
int current_space_; // from enum AllocationSpace.
|
|
|
|
ObjectIterator* iterator_; // object iterator for the current space.
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// A HeapIterator provides iteration over the whole heap It aggregates a the
|
|
|
|
// specific iterators for the different spaces as these can only iterate over
|
|
|
|
// one space only.
|
|
|
|
|
|
|
|
class HeapIterator BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
explicit HeapIterator();
|
|
|
|
virtual ~HeapIterator();
|
|
|
|
|
|
|
|
bool has_next();
|
|
|
|
HeapObject* next();
|
|
|
|
void reset();
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Perform the initialization.
|
|
|
|
void Init();
|
|
|
|
|
|
|
|
// Perform all necessary shutdown (destruction) work.
|
|
|
|
void Shutdown();
|
|
|
|
|
|
|
|
// Space iterator for iterating all the spaces.
|
|
|
|
SpaceIterator* space_iterator_;
|
|
|
|
// Object iterator for the space currently being iterated.
|
|
|
|
ObjectIterator* object_iterator_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Marking stack for tracing live objects.
|
|
|
|
|
|
|
|
class MarkingStack {
|
|
|
|
public:
|
|
|
|
void Initialize(Address low, Address high) {
|
|
|
|
top_ = low_ = reinterpret_cast<HeapObject**>(low);
|
|
|
|
high_ = reinterpret_cast<HeapObject**>(high);
|
|
|
|
overflowed_ = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_full() { return top_ >= high_; }
|
|
|
|
|
|
|
|
bool is_empty() { return top_ <= low_; }
|
|
|
|
|
|
|
|
bool overflowed() { return overflowed_; }
|
|
|
|
|
|
|
|
void clear_overflowed() { overflowed_ = false; }
|
|
|
|
|
2008-08-13 09:32:07 +00:00
|
|
|
// Push the (marked) object on the marking stack if there is room,
|
|
|
|
// otherwise mark the object as overflowed and wait for a rescan of the
|
|
|
|
// heap.
|
2008-08-06 10:02:49 +00:00
|
|
|
void Push(HeapObject* object) {
|
|
|
|
CHECK(object->IsHeapObject());
|
2008-08-13 09:32:07 +00:00
|
|
|
if (is_full()) {
|
|
|
|
object->SetOverflow();
|
|
|
|
overflowed_ = true;
|
|
|
|
} else {
|
|
|
|
*(top_++) = object;
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HeapObject* Pop() {
|
|
|
|
ASSERT(!is_empty());
|
2008-08-06 10:02:49 +00:00
|
|
|
HeapObject* object = *(--top_);
|
|
|
|
CHECK(object->IsHeapObject());
|
|
|
|
return object;
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
HeapObject** low_;
|
|
|
|
HeapObject** top_;
|
|
|
|
HeapObject** high_;
|
|
|
|
bool overflowed_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// A helper class to document/test C++ scopes where we do not
|
|
|
|
// expect a GC. Usage:
|
|
|
|
//
|
|
|
|
// /* Allocation not allowed: we cannot handle a GC in this scope. */
|
|
|
|
// { AssertNoAllocation nogc;
|
|
|
|
// ...
|
|
|
|
// }
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
class DisallowAllocationFailure {
|
|
|
|
public:
|
|
|
|
DisallowAllocationFailure() {
|
|
|
|
old_state_ = Heap::disallow_allocation_failure_;
|
|
|
|
Heap::disallow_allocation_failure_ = true;
|
|
|
|
}
|
|
|
|
~DisallowAllocationFailure() {
|
|
|
|
Heap::disallow_allocation_failure_ = old_state_;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
bool old_state_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class AssertNoAllocation {
|
|
|
|
public:
|
|
|
|
AssertNoAllocation() {
|
|
|
|
old_state_ = Heap::allow_allocation(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
~AssertNoAllocation() {
|
|
|
|
Heap::allow_allocation(old_state_);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool old_state_;
|
|
|
|
};
|
|
|
|
|
|
|
|
#else // ndef DEBUG
|
|
|
|
|
|
|
|
class AssertNoAllocation {
|
|
|
|
public:
|
|
|
|
AssertNoAllocation() { }
|
|
|
|
~AssertNoAllocation() { }
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
|
|
|
// The HeapProfiler writes data to the log files, which can be postprocessed
|
|
|
|
// to generate .hp files for use by the GHC/Valgrind tool hp2ps.
|
|
|
|
class HeapProfiler {
|
|
|
|
public:
|
|
|
|
// Write a single heap sample to the log file.
|
|
|
|
static void WriteSample();
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Update the array info with stats from obj.
|
|
|
|
static void CollectStats(HeapObject* obj, HistogramInfo* info);
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2008-07-30 08:49:36 +00:00
|
|
|
// GCTracer collects and prints ONE line after each garbage collector
|
|
|
|
// invocation IFF --trace_gc is used.
|
|
|
|
|
|
|
|
class GCTracer BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
GCTracer();
|
|
|
|
|
|
|
|
~GCTracer();
|
|
|
|
|
|
|
|
// Sets the collector.
|
|
|
|
void set_collector(GarbageCollector collector) { collector_ = collector; }
|
|
|
|
|
|
|
|
// Sets the GC count.
|
|
|
|
void set_gc_count(int count) { gc_count_ = count; }
|
|
|
|
|
|
|
|
// Sets the full GC count.
|
|
|
|
void set_full_gc_count(int count) { full_gc_count_ = count; }
|
|
|
|
|
|
|
|
// Sets the flag that this is a compacting full GC.
|
|
|
|
void set_is_compacting() { is_compacting_ = true; }
|
|
|
|
|
|
|
|
// Increment and decrement the count of marked objects.
|
|
|
|
void increment_marked_count() { ++marked_count_; }
|
|
|
|
void decrement_marked_count() { --marked_count_; }
|
|
|
|
|
|
|
|
int marked_count() { return marked_count_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Returns a string matching the collector.
|
|
|
|
const char* CollectorString();
|
|
|
|
|
|
|
|
// Returns size of object in heap (in MB).
|
|
|
|
double SizeOfHeapObjects() {
|
|
|
|
return (static_cast<double>(Heap::SizeOfObjects())) / MB;
|
|
|
|
}
|
|
|
|
|
|
|
|
double start_time_; // Timestamp set in the constructor.
|
|
|
|
double start_size_; // Size of objects in heap set in constructor.
|
|
|
|
GarbageCollector collector_; // Type of collector.
|
|
|
|
|
|
|
|
// A count (including this one, eg, the first collection is 1) of the
|
|
|
|
// number of garbage collections.
|
|
|
|
int gc_count_;
|
|
|
|
|
|
|
|
// A count (including this one) of the number of full garbage collections.
|
|
|
|
int full_gc_count_;
|
|
|
|
|
|
|
|
// True if the current GC is a compacting full collection, false
|
|
|
|
// otherwise.
|
|
|
|
bool is_compacting_;
|
|
|
|
|
|
|
|
// True if the *previous* full GC cwas a compacting collection (will be
|
|
|
|
// false if there has not been a previous full GC).
|
|
|
|
bool previous_has_compacted_;
|
|
|
|
|
|
|
|
// On a full GC, a count of the number of marked objects. Incremented
|
|
|
|
// when an object is marked and decremented when an object's mark bit is
|
|
|
|
// cleared. Will be zero on a scavenge collection.
|
|
|
|
int marked_count_;
|
|
|
|
|
|
|
|
// The count from the end of the previous full GC. Will be zero if there
|
|
|
|
// was no previous full GC.
|
|
|
|
int previous_marked_count_;
|
|
|
|
};
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_HEAP_H_
|