Large diffs are not rendered by default.

@@ -30,8 +30,6 @@
#ifndef V8_ATOMICOPS_INTERNALS_MIPS_GCC_H_
#define V8_ATOMICOPS_INTERNALS_MIPS_GCC_H_

#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")

namespace v8 {
namespace internal {

@@ -111,9 +109,9 @@ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,

inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
ATOMICOPS_COMPILER_BARRIER();
MemoryBarrier();
Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment);
ATOMICOPS_COMPILER_BARRIER();
MemoryBarrier();
return res;
}

@@ -126,19 +124,16 @@ inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
ATOMICOPS_COMPILER_BARRIER();
Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
ATOMICOPS_COMPILER_BARRIER();
MemoryBarrier();
return res;
}

inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
ATOMICOPS_COMPILER_BARRIER();
Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
ATOMICOPS_COMPILER_BARRIER();
return res;
MemoryBarrier();
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}

inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
@@ -176,6 +171,4 @@ inline Atomic32 Release_Load(volatile const Atomic32* ptr) {

} } // namespace v8::internal

#undef ATOMICOPS_COMPILER_BARRIER

#endif // V8_ATOMICOPS_INTERNALS_MIPS_GCC_H_
@@ -1086,11 +1086,13 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
CHECK_NOT_EMPTY_HANDLE(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
result, factory->length_string(),
factory->undefined_value(), DONT_ENUM));
factory->undefined_value(), DONT_ENUM,
Object::FORCE_TAGGED));
CHECK_NOT_EMPTY_HANDLE(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
result, factory->callee_string(),
factory->undefined_value(), DONT_ENUM));
factory->undefined_value(), DONT_ENUM,
Object::FORCE_TAGGED));

#ifdef DEBUG
LookupResult lookup(isolate);
@@ -1320,10 +1322,11 @@ void Genesis::InitializeExperimentalGlobal() {
if (FLAG_harmony_array_buffer) {
// -- A r r a y B u f f e r
Handle<JSFunction> array_buffer_fun =
InstallFunction(global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSize,
isolate()->initial_object_prototype(),
Builtins::kIllegal, true, true);
InstallFunction(
global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate()->initial_object_prototype(),
Builtins::kIllegal, true, true);
native_context()->set_array_buffer_fun(*array_buffer_fun);
}

@@ -1574,6 +1577,11 @@ void Genesis::InstallExperimentalNativeFunctions() {
}
if (FLAG_harmony_observation) {
INSTALL_NATIVE(JSFunction, "NotifyChange", observers_notify_change);
INSTALL_NATIVE(JSFunction, "EnqueueSpliceRecord", observers_enqueue_splice);
INSTALL_NATIVE(JSFunction, "BeginPerformSplice",
observers_begin_perform_splice);
INSTALL_NATIVE(JSFunction, "EndPerformSplice",
observers_end_perform_splice);
INSTALL_NATIVE(JSFunction, "DeliverChangeRecords",
observers_deliver_changes);
}
@@ -1604,19 +1612,23 @@ Handle<JSFunction> Genesis::InstallInternalArray(
factory()->NewJSObject(isolate()->object_function(), TENURED);
SetPrototype(array_function, prototype);

array_function->shared()->set_construct_stub(
isolate()->builtins()->builtin(Builtins::kCommonArrayConstructCode));
if (FLAG_optimize_constructed_arrays) {
InternalArrayConstructorStub internal_array_constructor_stub(isolate());
Handle<Code> code = internal_array_constructor_stub.GetCode(isolate());
array_function->shared()->set_construct_stub(*code);
} else {
array_function->shared()->set_construct_stub(
isolate()->builtins()->builtin(Builtins::kCommonArrayConstructCode));
}

array_function->shared()->DontAdaptArguments();

MaybeObject* maybe_map = array_function->initial_map()->Copy();
Map* new_map;
if (!maybe_map->To(&new_map)) return Handle<JSFunction>::null();
new_map->set_elements_kind(elements_kind);
array_function->set_initial_map(new_map);
Handle<Map> original_map(array_function->initial_map());
Handle<Map> initial_map = factory()->CopyMap(original_map);
initial_map->set_elements_kind(elements_kind);
array_function->set_initial_map(*initial_map);

// Make "length" magic on instances.
Handle<Map> initial_map(array_function->initial_map());
Handle<DescriptorArray> array_descriptors(
factory()->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*array_descriptors);
@@ -1870,14 +1882,11 @@ bool Genesis::InstallNatives() {
{
Handle<JSFunction> array_function =
InstallInternalArray(builtins, "InternalArray", FAST_HOLEY_ELEMENTS);
if (array_function.is_null()) return false;
native_context()->set_internal_array_function(*array_function);
}

{
Handle<JSFunction> array_function =
InstallInternalArray(builtins, "InternalPackedArray", FAST_ELEMENTS);
if (array_function.is_null()) return false;
InstallInternalArray(builtins, "InternalPackedArray", FAST_ELEMENTS);
}

if (FLAG_disable_native_files) {
@@ -2129,7 +2138,8 @@ void Genesis::InstallJSFunctionResultCaches() {
#undef F
;

Handle<FixedArray> caches = FACTORY->NewFixedArray(kNumberOfCaches, TENURED);
Handle<FixedArray> caches =
factory()->NewFixedArray(kNumberOfCaches, TENURED);

int index = 0;

@@ -2148,7 +2158,7 @@ void Genesis::InstallJSFunctionResultCaches() {

void Genesis::InitializeNormalizedMapCaches() {
Handle<FixedArray> array(
FACTORY->NewFixedArray(NormalizedMapCache::kEntries, TENURED));
factory()->NewFixedArray(NormalizedMapCache::kEntries, TENURED));
native_context()->set_normalized_map_cache(NormalizedMapCache::cast(*array));
}

@@ -2508,14 +2518,13 @@ void Genesis::TransferIndexedProperties(Handle<JSObject> from,
// Cloning the elements array is sufficient.
Handle<FixedArray> from_elements =
Handle<FixedArray>(FixedArray::cast(from->elements()));
Handle<FixedArray> to_elements = FACTORY->CopyFixedArray(from_elements);
Handle<FixedArray> to_elements = factory()->CopyFixedArray(from_elements);
to->set_elements(*to_elements);
}


void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {
HandleScope outer(isolate());
Factory* factory = isolate()->factory();

ASSERT(!from->IsJSArray());
ASSERT(!to->IsJSArray());
@@ -2525,7 +2534,7 @@ void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {

// Transfer the prototype (new map is needed).
Handle<Map> old_to_map = Handle<Map>(to->map());
Handle<Map> new_to_map = factory->CopyMap(old_to_map);
Handle<Map> new_to_map = factory()->CopyMap(old_to_map);
new_to_map->set_prototype(from->map()->prototype());
to->set_map(*new_to_map);
}
@@ -65,13 +65,14 @@ class SourceCodeCache BASE_EMBEDDED {
}

void Add(Vector<const char> name, Handle<SharedFunctionInfo> shared) {
HandleScope scope(shared->GetIsolate());
Isolate* isolate = shared->GetIsolate();
Factory* factory = isolate->factory();
HandleScope scope(isolate);
int length = cache_->length();
Handle<FixedArray> new_array =
FACTORY->NewFixedArray(length + 2, TENURED);
Handle<FixedArray> new_array = factory->NewFixedArray(length + 2, TENURED);
cache_->CopyTo(0, *new_array, 0, cache_->length());
cache_ = *new_array;
Handle<String> str = FACTORY->NewStringFromAscii(name, TENURED);
Handle<String> str = factory->NewStringFromAscii(name, TENURED);
cache_->set(length, *str);
cache_->set(length + 1, *shared);
Script::cast(shared->script())->set_type(Smi::FromInt(type_));
@@ -194,64 +194,6 @@ BUILTIN(EmptyFunction) {
}


RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure) {
// If we get 2 arguments then they are the stub parameters (constructor, type
// info). If we get 3, then the first one is a pointer to the arguments
// passed by the caller.
Arguments empty_args(0, NULL);
bool no_caller_args = args.length() == 2;
ASSERT(no_caller_args || args.length() == 3);
int parameters_start = no_caller_args ? 0 : 1;
Arguments* caller_args = no_caller_args
? &empty_args
: reinterpret_cast<Arguments*>(args[0]);
Handle<JSFunction> constructor = args.at<JSFunction>(parameters_start);
Handle<Object> type_info = args.at<Object>(parameters_start + 1);

bool holey = false;
if (caller_args->length() == 1 && (*caller_args)[0]->IsSmi()) {
int value = Smi::cast((*caller_args)[0])->value();
holey = (value > 0 && value < JSObject::kInitialMaxFastElementArray);
}

JSArray* array;
MaybeObject* maybe_array;
if (*type_info != isolate->heap()->undefined_value() &&
JSGlobalPropertyCell::cast(*type_info)->value()->IsSmi()) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info);
Smi* smi = Smi::cast(cell->value());
ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
if (holey && !IsFastHoleyElementsKind(to_kind)) {
to_kind = GetHoleyElementsKind(to_kind);
// Update the allocation site info to reflect the advice alteration.
cell->set_value(Smi::FromInt(to_kind));
}

maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
*constructor, type_info);
if (!maybe_array->To(&array)) return maybe_array;
} else {
ElementsKind kind = constructor->initial_map()->elements_kind();
ASSERT(kind == GetInitialFastElementsKind());
maybe_array = isolate->heap()->AllocateJSObject(*constructor);
if (!maybe_array->To(&array)) return maybe_array;
// We might need to transition to holey
if (holey) {
kind = GetHoleyElementsKind(kind);
maybe_array = array->TransitionElementsKind(kind);
if (maybe_array->IsFailure()) return maybe_array;
}
}

maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
DONT_INITIALIZE_ARRAY_ELEMENTS);
if (maybe_array->IsFailure()) return maybe_array;
maybe_array = ArrayConstructInitializeElements(array, caller_args);
if (maybe_array->IsFailure()) return maybe_array;
return array;
}


static MaybeObject* ArrayCodeGenericCommon(Arguments* args,
Isolate* isolate,
JSFunction* constructor) {
@@ -563,7 +505,7 @@ BUILTIN(ArrayPush) {
}

// Add the provided values.
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
for (int index = 0; index < to_add; index++) {
elms->set(index + len, args[index + 1], mode);
@@ -612,7 +554,7 @@ BUILTIN(ArrayPush) {
}

// Add the provided values.
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
int index;
for (index = 0; index < to_add; index++) {
Object* arg = args[index + 1];
@@ -695,7 +637,7 @@ BUILTIN(ArrayShift) {
// Shift the elements.
if (elms_obj->IsFixedArray()) {
FixedArray* elms = FixedArray::cast(elms_obj);
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
heap->MoveElements(elms, 0, 1, len - 1);
elms->set(len - 1, heap->the_hole_value());
} else {
@@ -762,12 +704,12 @@ BUILTIN(ArrayUnshift) {
elms = new_elms;
array->set_elements(elms);
} else {
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
heap->MoveElements(elms, to_add, 0, len);
}

// Add the provided values.
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
for (int i = 0; i < to_add; i++) {
elms->set(i, args[i + 1], mode);
@@ -898,7 +840,7 @@ BUILTIN(ArraySlice) {
result_len,
result_len);

AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
if (result_len == 0) return maybe_array;
if (!maybe_array->To(&result_array)) return maybe_array;

@@ -1000,7 +942,7 @@ BUILTIN(ArraySplice) {
if (!maybe_array->To(&result_array)) return maybe_array;

if (actual_delete_count > 0) {
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_failure = accessor->CopyElements(
NULL, actual_start, elements_kind, result_array->elements(),
@@ -1025,7 +967,7 @@ BUILTIN(ArraySplice) {
MoveDoubleElements(elms, delta, elms, 0, actual_start);
} else {
FixedArray* elms = FixedArray::cast(elms_obj);
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
heap->MoveElements(elms, delta, 0, actual_start);
}

@@ -1041,7 +983,7 @@ BUILTIN(ArraySplice) {
FillWithHoles(elms, new_length, len);
} else {
FixedArray* elms = FixedArray::cast(elms_obj);
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
heap->MoveElements(elms, actual_start + item_count,
actual_start + actual_delete_count,
(len - actual_delete_count - actual_start));
@@ -1062,7 +1004,7 @@ BUILTIN(ArraySplice) {
MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
if (!maybe_obj->To(&new_elms)) return maybe_obj;

AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;

ElementsKind kind = array->GetElementsKind();
ElementsAccessor* accessor = array->GetElementsAccessor();
@@ -1083,7 +1025,7 @@ BUILTIN(ArraySplice) {
elms_obj = new_elms;
elms_changed = true;
} else {
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
heap->MoveElements(elms, actual_start + item_count,
actual_start + actual_delete_count,
(len - actual_delete_count - actual_start));
@@ -1102,7 +1044,7 @@ BUILTIN(ArraySplice) {
}
} else {
FixedArray* elms = FixedArray::cast(elms_obj);
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
for (int k = actual_start; k < actual_start + item_count; k++) {
elms->set(k, args[3 + k - actual_start], mode);
@@ -1466,6 +1408,11 @@ static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
}


static void Generate_LoadIC_Slow(MacroAssembler* masm) {
LoadIC::GenerateRuntimeGetProperty(masm);
}


static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
KeyedLoadIC::GenerateInitialize(masm);
}
@@ -143,6 +143,8 @@ enum BuiltinExtraArguments {
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
Code::kNoExtraICState) \
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \
Code::kNoExtraICState) \
V(LoadIC_Slow, LOAD_IC, GENERIC, \
Code::kNoExtraICState) \
\
V(KeyedLoadIC_Initialize, KEYED_LOAD_IC, UNINITIALIZED, \
@@ -36,6 +36,8 @@ static int fatal_error_handler_nesting_depth = 0;

// Contains protection against recursive calls (faults while handling faults).
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
i::AllowHandleDereference allow_deref;
i::AllowDeferredHandleDereference allow_deferred_deref;
fflush(stdout);
fflush(stderr);
fatal_error_handler_nesting_depth++;

Large diffs are not rendered by default.

@@ -45,7 +45,8 @@ CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
function_mode_(NOT_JS_FUNCTION_STUB_MODE),
register_params_(NULL),
deoptimization_handler_(NULL),
miss_handler_(IC_Utility(IC::kUnreachable), Isolate::Current()) { }
miss_handler_(IC_Utility(IC::kUnreachable), Isolate::Current()),
has_miss_handler_(false) { }


bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
@@ -304,6 +305,27 @@ void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
}


InlineCacheState ICCompareStub::GetICState() {
CompareIC::State state = Max(left_, right_);
switch (state) {
case CompareIC::UNINITIALIZED:
return ::v8::internal::UNINITIALIZED;
case CompareIC::SMI:
case CompareIC::NUMBER:
case CompareIC::INTERNALIZED_STRING:
case CompareIC::STRING:
case CompareIC::UNIQUE_NAME:
case CompareIC::OBJECT:
case CompareIC::KNOWN_OBJECT:
return MONOMORPHIC;
case CompareIC::GENERIC:
return ::v8::internal::GENERIC;
}
UNREACHABLE();
return ::v8::internal::UNINITIALIZED;
}


void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
ASSERT(*known_map_ != NULL);
Isolate* isolate = new_object->GetIsolate();
@@ -410,36 +432,44 @@ void ICCompareStub::Generate(MacroAssembler* masm) {

void CompareNilICStub::Record(Handle<Object> object) {
ASSERT(types_ != Types::FullCompare());
if (equality_kind_ == kStrictEquality) {
// When testing for strict equality only one value will evaluate to true
types_.RemoveAll();
types_.Add((nil_value_ == kNullValue) ? NULL_TYPE:
UNDEFINED);
if (object->IsNull()) {
types_.Add(NULL_TYPE);
} else if (object->IsUndefined()) {
types_.Add(UNDEFINED);
} else if (object->IsUndetectableObject() ||
object->IsOddball() ||
!object->IsHeapObject()) {
types_ = Types::FullCompare();
} else if (IsMonomorphic()) {
types_ = Types::FullCompare();
} else {
if (object->IsNull()) {
types_.Add(NULL_TYPE);
} else if (object->IsUndefined()) {
types_.Add(UNDEFINED);
} else if (object->IsUndetectableObject() ||
object->IsOddball() ||
!object->IsHeapObject()) {
types_ = Types::FullCompare();
} else if (IsMonomorphic()) {
types_ = Types::FullCompare();
} else {
types_.Add(MONOMORPHIC_MAP);
}
types_.Add(MONOMORPHIC_MAP);
}
}


void CompareNilICStub::Types::TraceTransition(Types to) const {
#ifdef DEBUG
if (!FLAG_trace_ic) return;
char buffer[100];
NoAllocationStringAllocator allocator(buffer,
static_cast<unsigned>(sizeof(buffer)));
StringStream stream(&allocator);
stream.Add("[CompareNilIC : ");
Print(&stream);
stream.Add("=>");
to.Print(&stream);
stream.Add("]\n");
stream.OutputToStdOut();
#endif
}


void CompareNilICStub::PrintName(StringStream* stream) {
stream->Add("CompareNilICStub_");
types_.Print(stream);
stream->Add((nil_value_ == kNullValue) ? "(NullValue|":
"(UndefinedValue|");
stream->Add((equality_kind_ == kStrictEquality) ? "StrictEquality)":
"NonStrictEquality)");
}


@@ -554,6 +584,14 @@ void CallConstructStub::PrintName(StringStream* stream) {
}


bool ToBooleanStub::Record(Handle<Object> object) {
Types old_types(types_);
bool to_boolean_value = types_.Record(object);
old_types.TraceTransition(types_);
return to_boolean_value;
}


void ToBooleanStub::PrintName(StringStream* stream) {
stream->Add("ToBooleanStub_");
types_.Print(stream);
@@ -577,17 +615,19 @@ void ToBooleanStub::Types::Print(StringStream* stream) const {


void ToBooleanStub::Types::TraceTransition(Types to) const {
#ifdef DEBUG
if (!FLAG_trace_ic) return;
char buffer[100];
NoAllocationStringAllocator allocator(buffer,
static_cast<unsigned>(sizeof(buffer)));
StringStream stream(&allocator);
stream.Add("[ToBooleanIC (");
stream.Add("[ToBooleanIC : ");
Print(&stream);
stream.Add("->");
stream.Add("=>");
to.Print(&stream);
stream.Add(")]\n");
stream.Add("]\n");
stream.OutputToStdOut();
#endif
}


@@ -749,4 +789,19 @@ ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
}


void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
InternalArrayNoArgumentConstructorStub stub1(FAST_ELEMENTS);
InstallDescriptor(isolate, &stub1);
InternalArraySingleArgumentConstructorStub stub2(FAST_ELEMENTS);
InstallDescriptor(isolate, &stub2);
InternalArrayNArgumentsConstructorStub stub3(FAST_ELEMENTS);
InstallDescriptor(isolate, &stub3);
}

InternalArrayConstructorStub::InternalArrayConstructorStub(
Isolate* isolate) {
InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
}


} } // namespace v8::internal

Large diffs are not rendered by default.

@@ -58,13 +58,12 @@ Comment::~Comment() {
#undef __


void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
#ifdef DEBUG
void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
bool print_source = false;
bool print_ast = false;
const char* ftype;

if (Isolate::Current()->bootstrapper()->IsActive()) {
if (info->isolate()->bootstrapper()->IsActive()) {
print_source = FLAG_print_builtin_source;
print_ast = FLAG_print_builtin_ast;
ftype = "builtin";
@@ -75,17 +74,18 @@ void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
}

if (FLAG_trace_codegen || print_source || print_ast) {
PrintF("*** Generate code for %s function: ", ftype);
PrintF("[generating %s code for %s function: ", kind, ftype);
if (info->IsStub()) {
const char* name =
CodeStub::MajorName(info->code_stub()->MajorKey(), true);
PrintF("%s", name == NULL ? "<unknown>" : name);
} else {
info->function()->name()->ShortPrint();
PrintF("%s", *info->function()->debug_name()->ToCString());
}
PrintF(" ***\n");
PrintF("]\n");
}

#ifdef DEBUG
if (!info->IsStub() && print_source) {
PrintF("--- Source from AST ---\n%s\n",
PrettyPrinter().PrintProgram(info->function()));
@@ -113,18 +113,6 @@ class ElementsTransitionGenerator : public AllStatic {
};


class SeqStringSetCharGenerator : public AllStatic {
public:
static void Generate(MacroAssembler* masm,
String::Encoding encoding,
Register string,
Register index,
Register value);
private:
DISALLOW_COPY_AND_ASSIGN(SeqStringSetCharGenerator);
};


} } // namespace v8::internal

#endif // V8_CODEGEN_H_
@@ -36,6 +36,7 @@
#include "deoptimizer.h"
#include "full-codegen.h"
#include "gdb-jit.h"
#include "typing.h"
#include "hydrogen.h"
#include "isolate-inl.h"
#include "lithium.h"
@@ -361,11 +362,11 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
isolate()->GetHTracer()->TraceCompilation(info());
}
Handle<Context> native_context(
info()->closure()->context()->native_context());
oracle_ = new(info()->zone()) TypeFeedbackOracle(
code, native_context, isolate(), info()->zone());
graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info(), oracle_);

// Type-check the function.
AstTyper::Type(info());

graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info());

Timer t(this, &time_taken_to_create_graph_);
graph_ = graph_builder_->CreateGraph();
@@ -392,9 +393,9 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
}

OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
AssertNoAllocation no_gc;
NoHandleAllocation no_handles(isolate());
HandleDereferenceGuard no_deref(isolate(), HandleDereferenceGuard::DISALLOW);
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;

ASSERT(last_status() == SUCCEEDED);
Timer t(this, &time_taken_to_optimize_);
@@ -423,8 +424,7 @@ OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
// graph creation. To make sure that we don't encounter inconsistencies
// between graph creation and code generation, we disallow accessing
// objects through deferred handles during the latter, with exceptions.
HandleDereferenceGuard no_deref_deferred(
isolate(), HandleDereferenceGuard::DISALLOW_DEFERRED);
DisallowDeferredHandleDereference no_deferred_handle_deref;
Handle<Code> optimized_code = chunk_->Codegen();
if (optimized_code.is_null()) {
info()->set_bailout_reason("code generation failed");
@@ -649,7 +649,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
// in that case too.

// Create a script object describing the script to be compiled.
Handle<Script> script = FACTORY->NewScript(source);
Handle<Script> script = isolate->factory()->NewScript(source);
if (natives == NATIVES_CODE) {
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
}
@@ -771,13 +771,6 @@ static bool InstallFullCode(CompilationInfo* info) {
int expected = lit->expected_property_count();
SetExpectedNofPropertiesFromEstimate(shared, expected);

// Set the optimization hints after performing lazy compilation, as
// these are not set when the function is set up as a lazily
// compiled function.
shared->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());

// Check the function has compiled code.
ASSERT(shared->is_compiled());
shared->set_code_age(0);
@@ -957,9 +950,6 @@ void Compiler::RecompileParallel(Handle<JSFunction> closure) {
if (status == OptimizingCompiler::SUCCEEDED) {
info.Detach();
shared->code()->set_profiler_ticks(0);
// Do a scavenge to put off the next scavenge as far as possible.
// This may ease the issue that GVN blocks the next scavenge.
isolate->heap()->CollectGarbage(NEW_SPACE, "parallel recompile");
isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
} else if (status == OptimizingCompiler::BAILED_OUT) {
isolate->clear_pending_exception();
@@ -1054,6 +1044,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
info.SetLanguageMode(literal->scope()->language_mode());

Isolate* isolate = info.isolate();
Factory* factory = isolate->factory();
LiveEditFunctionTracker live_edit_tracker(isolate, literal);
// Determine if the function can be lazily compiled. This is necessary to
// allow some of our builtin JS files to be lazily compiled. These
@@ -1083,7 +1074,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,

// Create a shared function info object.
Handle<SharedFunctionInfo> result =
FACTORY->NewSharedFunctionInfo(literal->name(),
factory->NewSharedFunctionInfo(literal->name(),
literal->materialized_literal_count(),
literal->is_generator(),
info.code(),
@@ -1120,9 +1111,6 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
function_info->set_is_anonymous(lit->is_anonymous());
function_info->set_is_toplevel(is_toplevel);
function_info->set_inferred_name(*lit->inferred_name());
function_info->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
function_info->set_allows_lazy_compilation_without_context(
lit->AllowsLazyCompilationWithoutContext());
@@ -449,7 +449,6 @@ class OptimizingCompiler: public ZoneObject {
public:
explicit OptimizingCompiler(CompilationInfo* info)
: info_(info),
oracle_(NULL),
graph_builder_(NULL),
graph_(NULL),
chunk_(NULL),
@@ -478,7 +477,6 @@ class OptimizingCompiler: public ZoneObject {

private:
CompilationInfo* info_;
TypeFeedbackOracle* oracle_;
HOptimizedGraphBuilder* graph_builder_;
HGraph* graph_;
LChunk* chunk_;
@@ -172,6 +172,11 @@ enum BindingFlags {
V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap) \
V(PROXY_ENUMERATE_INDEX, JSFunction, proxy_enumerate) \
V(OBSERVERS_NOTIFY_CHANGE_INDEX, JSFunction, observers_notify_change) \
V(OBSERVERS_ENQUEUE_SPLICE_INDEX, JSFunction, observers_enqueue_splice) \
V(OBSERVERS_BEGIN_SPLICE_INDEX, JSFunction, \
observers_begin_perform_splice) \
V(OBSERVERS_END_SPLICE_INDEX, JSFunction, \
observers_end_perform_splice) \
V(OBSERVERS_DELIVER_CHANGES_INDEX, JSFunction, observers_deliver_changes) \
V(GENERATOR_FUNCTION_MAP_INDEX, Map, generator_function_map) \
V(STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX, Map, \
@@ -317,6 +322,9 @@ class Context: public FixedArray {
DERIVED_SET_TRAP_INDEX,
PROXY_ENUMERATE_INDEX,
OBSERVERS_NOTIFY_CHANGE_INDEX,
OBSERVERS_ENQUEUE_SPLICE_INDEX,
OBSERVERS_BEGIN_SPLICE_INDEX,
OBSERVERS_END_SPLICE_INDEX,
OBSERVERS_DELIVER_CHANGES_INDEX,
GENERATOR_FUNCTION_MAP_INDEX,
STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX,
@@ -461,10 +461,7 @@ void CpuProfiler::StartProcessorIfNotStarted() {
// Enumerate stuff we already have in the heap.
if (isolate_->heap()->HasBeenSetUp()) {
if (!FLAG_prof_browser_mode) {
bool saved_log_code_flag = FLAG_log_code;
FLAG_log_code = true;
isolate_->logger()->LogCodeObjects();
FLAG_log_code = saved_log_code_flag;
}
isolate_->logger()->LogCompiledFunctions();
isolate_->logger()->LogAccessorCallbacks();
@@ -238,7 +238,7 @@ class ExecArgs {


// Gets the optional timeouts from the arguments to the system() call.
static bool GetTimeouts(const Arguments& args,
static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args,
int* read_timeout,
int* total_timeout) {
if (args.Length() > 3) {
@@ -448,42 +448,47 @@ static bool WaitForChild(int pid,


// Implementation of the system() function (see d8.h for details).
Handle<Value> Shell::System(const Arguments& args) {
void Shell::System(const v8::FunctionCallbackInfo<v8::Value>& args) {
HandleScope scope(args.GetIsolate());
int read_timeout = -1;
int total_timeout = -1;
if (!GetTimeouts(args, &read_timeout, &total_timeout)) return v8::Undefined();
if (!GetTimeouts(args, &read_timeout, &total_timeout)) return;
Handle<Array> command_args;
if (args.Length() > 1) {
if (!args[1]->IsArray()) {
return ThrowException(String::New("system: Argument 2 must be an array"));
ThrowException(String::New("system: Argument 2 must be an array"));
return;
}
command_args = Handle<Array>::Cast(args[1]);
} else {
command_args = Array::New(0);
}
if (command_args->Length() > ExecArgs::kMaxArgs) {
return ThrowException(String::New("Too many arguments to system()"));
ThrowException(String::New("Too many arguments to system()"));
return;
}
if (args.Length() < 1) {
return ThrowException(String::New("Too few arguments to system()"));
ThrowException(String::New("Too few arguments to system()"));
return;
}

struct timeval start_time;
gettimeofday(&start_time, NULL);

ExecArgs exec_args;
if (!exec_args.Init(args[0], command_args)) {
return v8::Undefined();
return;
}
int exec_error_fds[2];
int stdout_fds[2];

if (pipe(exec_error_fds) != 0) {
return ThrowException(String::New("pipe syscall failed."));
ThrowException(String::New("pipe syscall failed."));
return;
}
if (pipe(stdout_fds) != 0) {
return ThrowException(String::New("pipe syscall failed."));
ThrowException(String::New("pipe syscall failed."));
return;
}

pid_t pid = fork();
@@ -499,58 +504,64 @@ Handle<Value> Shell::System(const Arguments& args) {
OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);

if (!ChildLaunchedOK(exec_error_fds)) return v8::Undefined();
if (!ChildLaunchedOK(exec_error_fds)) return;

Handle<Value> accumulator = GetStdout(stdout_fds[kReadFD],
start_time,
read_timeout,
total_timeout);
if (accumulator->IsUndefined()) {
kill(pid, SIGINT); // On timeout, kill the subprocess.
return accumulator;
args.GetReturnValue().Set(accumulator);
return;
}

if (!WaitForChild(pid,
child_waiter,
start_time,
read_timeout,
total_timeout)) {
return v8::Undefined();
return;
}

return scope.Close(accumulator);
args.GetReturnValue().Set(accumulator);
}


Handle<Value> Shell::ChangeDirectory(const Arguments& args) {
void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "chdir() takes one argument";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
String::Utf8Value directory(args[0]);
if (*directory == NULL) {
const char* message = "os.chdir(): String conversion of argument failed.";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
if (chdir(*directory) != 0) {
return ThrowException(String::New(strerror(errno)));
ThrowException(String::New(strerror(errno)));
return;
}
return v8::Undefined();
}


Handle<Value> Shell::SetUMask(const Arguments& args) {
void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "umask() takes one argument";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
if (args[0]->IsNumber()) {
mode_t mask = args[0]->Int32Value();
int previous = umask(mask);
return Number::New(previous);
args.GetReturnValue().Set(previous);
return;
} else {
const char* message = "umask() argument must be numeric";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
}

@@ -598,79 +609,85 @@ static bool mkdirp(char* directory, mode_t mask) {
}


Handle<Value> Shell::MakeDirectory(const Arguments& args) {
void Shell::MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
mode_t mask = 0777;
if (args.Length() == 2) {
if (args[1]->IsNumber()) {
mask = args[1]->Int32Value();
} else {
const char* message = "mkdirp() second argument must be numeric";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
} else if (args.Length() != 1) {
const char* message = "mkdirp() takes one or two arguments";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
String::Utf8Value directory(args[0]);
if (*directory == NULL) {
const char* message = "os.mkdirp(): String conversion of argument failed.";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
mkdirp(*directory, mask);
return v8::Undefined();
}


Handle<Value> Shell::RemoveDirectory(const Arguments& args) {
void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "rmdir() takes one or two arguments";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
String::Utf8Value directory(args[0]);
if (*directory == NULL) {
const char* message = "os.rmdir(): String conversion of argument failed.";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
rmdir(*directory);
return v8::Undefined();
}


Handle<Value> Shell::SetEnvironment(const Arguments& args) {
void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 2) {
const char* message = "setenv() takes two arguments";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
String::Utf8Value var(args[0]);
String::Utf8Value value(args[1]);
if (*var == NULL) {
const char* message =
"os.setenv(): String conversion of variable name failed.";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
if (*value == NULL) {
const char* message =
"os.setenv(): String conversion of variable contents failed.";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
setenv(*var, *value, 1);
return v8::Undefined();
}


Handle<Value> Shell::UnsetEnvironment(const Arguments& args) {
void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "unsetenv() takes one argument";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
String::Utf8Value var(args[0]);
if (*var == NULL) {
const char* message =
"os.setenv(): String conversion of variable name failed.";
return ThrowException(String::New(message));
ThrowException(String::New(message));
return;
}
unsetenv(*var);
return v8::Undefined();
}


Large diffs are not rendered by default.

@@ -300,45 +300,46 @@ class Shell : public i::AllStatic {
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // V8_SHARED

static Handle<Value> RealmCurrent(const Arguments& args);
static Handle<Value> RealmOwner(const Arguments& args);
static Handle<Value> RealmGlobal(const Arguments& args);
static Handle<Value> RealmCreate(const Arguments& args);
static Handle<Value> RealmDispose(const Arguments& args);
static Handle<Value> RealmSwitch(const Arguments& args);
static Handle<Value> RealmEval(const Arguments& args);
static Handle<Value> RealmSharedGet(Local<String> property,
const AccessorInfo& info);
static void RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmSharedGet(Local<String> property,
const PropertyCallbackInfo<Value>& info);
static void RealmSharedSet(Local<String> property,
Local<Value> value,
const AccessorInfo& info);

static Handle<Value> Print(const Arguments& args);
static Handle<Value> Write(const Arguments& args);
static Handle<Value> Quit(const Arguments& args);
static Handle<Value> Version(const Arguments& args);
static Handle<Value> EnableProfiler(const Arguments& args);
static Handle<Value> DisableProfiler(const Arguments& args);
static Handle<Value> Read(const Arguments& args);
static Handle<Value> ReadBuffer(const Arguments& args);
const PropertyCallbackInfo<void>& info);

static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Write(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Version(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EnableProfiler(const v8::FunctionCallbackInfo<v8::Value>& args);
static void DisableProfiler(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Read(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
static Handle<String> ReadFromStdin(Isolate* isolate);
static Handle<Value> ReadLine(const Arguments& args) {
return ReadFromStdin(args.GetIsolate());
static void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.GetReturnValue().Set(ReadFromStdin(args.GetIsolate()));
}
static Handle<Value> Load(const Arguments& args);
static Handle<Value> ArrayBuffer(const Arguments& args);
static Handle<Value> Int8Array(const Arguments& args);
static Handle<Value> Uint8Array(const Arguments& args);
static Handle<Value> Int16Array(const Arguments& args);
static Handle<Value> Uint16Array(const Arguments& args);
static Handle<Value> Int32Array(const Arguments& args);
static Handle<Value> Uint32Array(const Arguments& args);
static Handle<Value> Float32Array(const Arguments& args);
static Handle<Value> Float64Array(const Arguments& args);
static Handle<Value> Uint8ClampedArray(const Arguments& args);
static Handle<Value> ArrayBufferSlice(const Arguments& args);
static Handle<Value> ArraySubArray(const Arguments& args);
static Handle<Value> ArraySet(const Arguments& args);
static void Load(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ArrayBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Int8Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Uint8Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Int16Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Uint16Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Int32Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Uint32Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Float32Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Float64Array(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Uint8ClampedArray(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void ArrayBufferSlice(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ArraySubArray(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ArraySet(const v8::FunctionCallbackInfo<v8::Value>& args);
// The OS object on the global object contains methods for performing
// operating system calls:
//
@@ -365,14 +366,14 @@ class Shell : public i::AllStatic {
// with the current umask. Intermediate directories are created if necessary.
// An exception is not thrown if the directory already exists. Analogous to
// the "mkdir -p" command.
static Handle<Value> OSObject(const Arguments& args);
static Handle<Value> System(const Arguments& args);
static Handle<Value> ChangeDirectory(const Arguments& args);
static Handle<Value> SetEnvironment(const Arguments& args);
static Handle<Value> UnsetEnvironment(const Arguments& args);
static Handle<Value> SetUMask(const Arguments& args);
static Handle<Value> MakeDirectory(const Arguments& args);
static Handle<Value> RemoveDirectory(const Arguments& args);
static void OSObject(const v8::FunctionCallbackInfo<v8::Value>& args);
static void System(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
static void UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
static void MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);

static void AddOSMethods(Handle<ObjectTemplate> os_template);

@@ -412,9 +413,10 @@ class Shell : public i::AllStatic {
int32_t byteLength,
int32_t byteOffset,
int32_t element_size);
static Handle<Value> CreateExternalArray(const Arguments& args,
ExternalArrayType type,
int32_t element_size);
static void CreateExternalArray(
const v8::FunctionCallbackInfo<v8::Value>& args,
ExternalArrayType type,
int32_t element_size);
static void ExternalArrayWeakCallback(Isolate* isolate,
Persistent<Object>* object,
uint8_t* data);
@@ -121,7 +121,7 @@ BreakLocationIterator::~BreakLocationIterator() {


void BreakLocationIterator::Next() {
AssertNoAllocation nogc;
DisallowHeapAllocation no_gc;
ASSERT(!RinfoDone());

// Iterate through reloc info for code and original code stopping at each
@@ -211,14 +211,15 @@ void BreakLocationIterator::Next(int count) {
}


// Find the break point closest to the supplied address.
// Find the break point at the supplied address, or the closest one before
// the address.
void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
// Run through all break points to locate the one closest to the address.
int closest_break_point = 0;
int distance = kMaxInt;
while (!Done()) {
// Check if this break point is closer that what was previously found.
if (this->pc() < pc && pc - this->pc() < distance) {
if (this->pc() <= pc && pc - this->pc() < distance) {
closest_break_point = break_point();
distance = static_cast<int>(pc - this->pc());
// Check whether we can't get any closer.
@@ -619,14 +620,14 @@ void ScriptCache::Add(Handle<Script> script) {
(global_handles->Create(*script)));
global_handles->MakeWeak(reinterpret_cast<Object**>(script_.location()),
this,
NULL,
ScriptCache::HandleWeakScript);
entry->value = script_.location();
}


Handle<FixedArray> ScriptCache::GetScripts() {
Handle<FixedArray> instances = FACTORY->NewFixedArray(occupancy());
Factory* factory = Isolate::Current()->factory();
Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
int count = 0;
for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
ASSERT(entry->value != NULL);
@@ -664,12 +665,12 @@ void ScriptCache::Clear() {


void ScriptCache::HandleWeakScript(v8::Isolate* isolate,
v8::Persistent<v8::Value> obj,
v8::Persistent<v8::Value>* obj,
void* data) {
ScriptCache* script_cache = reinterpret_cast<ScriptCache*>(data);
// Find the location of the global handle.
Script** location =
reinterpret_cast<Script**>(Utils::OpenHandle(*obj).location());
reinterpret_cast<Script**>(Utils::OpenHandle(**obj).location());
ASSERT((*location)->IsScript());

// Remove the entry from the cache.
@@ -678,8 +679,7 @@ void ScriptCache::HandleWeakScript(v8::Isolate* isolate,
script_cache->collected_scripts_.Add(id);

// Clear the weak handle.
obj.Dispose(isolate);
obj.Clear();
obj->Dispose(isolate);
}


@@ -699,7 +699,7 @@ void Debug::SetUp(bool create_heap_objects) {


void Debug::HandleWeakDebugInfo(v8::Isolate* isolate,
v8::Persistent<v8::Value> obj,
v8::Persistent<v8::Value>* obj,
void* data) {
Debug* debug = reinterpret_cast<Isolate*>(isolate)->debug();
DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
@@ -727,7 +727,6 @@ DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
(global_handles->Create(debug_info)));
global_handles->MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
this,
NULL,
Debug::HandleWeakDebugInfo);
}

@@ -790,7 +789,7 @@ bool Debug::CompileDebuggerScript(int index) {
MessageLocation computed_location;
isolate->ComputeLocation(&computed_location);
Handle<Object> message = MessageHandler::MakeMessageObject(
"error_loading_debugger", &computed_location,
isolate, "error_loading_debugger", &computed_location,
Vector<Handle<Object> >::empty(), Handle<String>(), Handle<JSArray>());
ASSERT(!isolate->has_pending_exception());
if (!exception.is_null()) {
@@ -945,7 +944,9 @@ Object* Debug::Break(Arguments args) {
// Find the break point where execution has stopped.
BreakLocationIterator break_location_iterator(debug_info,
ALL_BREAK_LOCATIONS);
break_location_iterator.FindBreakLocationFromAddress(frame->pc());
// pc points to the instruction after the current one, possibly a break
// location as well. So the "- 1" to exclude it from the search.
break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);

// Check whether step next reached a new statement.
if (!StepNextContinue(&break_location_iterator, frame)) {
@@ -1240,15 +1241,11 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
// Get information in the break point.
BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
Handle<DebugInfo> debug_info = node->debug_info();
Handle<SharedFunctionInfo> shared(debug_info->shared());
int source_position = break_point_info->statement_position()->value();

// Source positions starts with zero.
ASSERT(source_position >= 0);

// Find the break point and clear it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
it.FindBreakLocationFromPosition(source_position);
it.FindBreakLocationFromAddress(debug_info->code()->entry() +
break_point_info->code_position()->value());
it.ClearBreakPoint(break_point_object);

// If there are no more break points left remove the debug info for this
@@ -1406,7 +1403,9 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {

// Find the break location where execution has stopped.
BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
it.FindBreakLocationFromAddress(frame->pc());
// pc points to the instruction after the current one, possibly a break
// location as well. So the "- 1" to exclude it from the search.
it.FindBreakLocationFromAddress(frame->pc() - 1);

// Compute whether or not the target is a call target.
bool is_load_or_store = false;
@@ -2025,7 +2024,7 @@ void Debug::PrepareForBreakPoints() {

// Ensure no GC in this scope as we are going to use gc_metadata
// field in the Code object to mark active functions.
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;

Object* active_code_marker = heap->the_hole_value();

@@ -2140,7 +2139,7 @@ Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
while (!done) {
{ // Extra scope for iterator and no-allocation.
heap->EnsureHeapIsIterable();
AssertNoAllocation no_alloc_during_heap_iteration;
DisallowHeapAllocation no_alloc_during_heap_iteration;
HeapIterator iterator(heap);
for (HeapObject* obj = iterator.next();
obj != NULL; obj = iterator.next()) {
@@ -2229,6 +2228,8 @@ Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
// Ensures the debug information is present for shared.
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
Handle<JSFunction> function) {
Isolate* isolate = shared->GetIsolate();

// Return if we already have the debug info for shared.
if (HasDebugInfo(shared)) {
ASSERT(shared->is_compiled());
@@ -2245,7 +2246,7 @@ bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
}

// Create the debug info object.
Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared);
Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);

// Add debug info to the list.
DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
@@ -2476,7 +2477,7 @@ void Debug::CreateScriptCache() {
// Scan heap for Script objects.
int count = 0;
HeapIterator iterator(heap);
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;

for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
@@ -190,7 +190,7 @@ class ScriptCache : private HashMap {

// Weak handle callback for scripts in the cache.
static void HandleWeakScript(v8::Isolate* isolate,
v8::Persistent<v8::Value> obj,
v8::Persistent<v8::Value>* obj,
void* data);

// List used during GC to temporarily store id's of collected scripts.
@@ -387,7 +387,7 @@ class Debug {

// Passed to MakeWeak.
static void HandleWeakDebugInfo(v8::Isolate* isolate,
v8::Persistent<v8::Value> obj,
v8::Persistent<v8::Value>* obj,
void* data);

friend class Debugger;
@@ -285,7 +285,7 @@ void Deoptimizer::VisitAllOptimizedFunctionsForContext(
Context* context, OptimizedFunctionVisitor* visitor) {
Isolate* isolate = context->GetIsolate();
ZoneScope zone_scope(isolate->runtime_zone(), DELETE_ON_EXIT);
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;

ASSERT(context->IsNativeContext());

@@ -313,7 +313,7 @@ void Deoptimizer::VisitAllOptimizedFunctionsForContext(
void Deoptimizer::VisitAllOptimizedFunctions(
Isolate* isolate,
OptimizedFunctionVisitor* visitor) {
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;

// Run through the list of all native contexts and deoptimize.
Object* context = isolate->heap()->native_contexts_list();
@@ -335,7 +335,7 @@ static void PartitionOptimizedFunctions(Context* context,
ZoneList<Code*>* partitions,
Zone* zone,
Object* undefined) {
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;
Object* current = context->get(Context::OPTIMIZED_FUNCTIONS_LIST);
Object* remainder_head = undefined;
Object* remainder_tail = undefined;
@@ -388,7 +388,7 @@ class DeoptimizeWithMatchingCodeFilter : public OptimizedFunctionFilter {


void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;

if (FLAG_trace_deopt) {
PrintF("[deoptimize all contexts]\n");
@@ -400,7 +400,7 @@ void Deoptimizer::DeoptimizeAll(Isolate* isolate) {


void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;
DeoptimizeAllFilter filter;
if (object->IsJSGlobalProxy()) {
Object* proto = object->GetPrototype();
@@ -451,7 +451,7 @@ void Deoptimizer::DeoptimizeAllFunctionsForContext(

void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate,
OptimizedFunctionFilter* filter) {
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;

// Run through the list of all native contexts and deoptimize.
Object* context = isolate->heap()->native_contexts_list();
@@ -463,7 +463,7 @@ void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate,


void Deoptimizer::HandleWeakDeoptimizedCode(v8::Isolate* isolate,
v8::Persistent<v8::Value> obj,
v8::Persistent<v8::Value>* obj,
void* parameter) {
DeoptimizingCodeListNode* node =
reinterpret_cast<DeoptimizingCodeListNode*>(parameter);
@@ -558,7 +558,10 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
? StackFrame::STUB
: StackFrame::JAVA_SCRIPT;
trace_ = TraceEnabledFor(type, frame_type);
ASSERT(HEAP->allow_allocation(false));
#ifdef DEBUG
CHECK(AllowHeapAllocation::IsAllowed());
disallow_heap_allocation_ = new DisallowHeapAllocation();
#endif // DEBUG
unsigned size = ComputeInputFrameSize();
input_ = new(size) FrameDescription(size, function);
input_->SetFrameType(frame_type);
@@ -608,6 +611,7 @@ void Deoptimizer::PrintFunctionName() {

Deoptimizer::~Deoptimizer() {
ASSERT(input_ == NULL && output_ == NULL);
ASSERT(disallow_heap_allocation_ == NULL);
}


@@ -619,7 +623,12 @@ void Deoptimizer::DeleteFrameDescriptions() {
delete[] output_;
input_ = NULL;
output_ = NULL;
ASSERT(!HEAP->allow_allocation(true));
#ifdef DEBUG
CHECK(!AllowHeapAllocation::IsAllowed());
CHECK(disallow_heap_allocation_ != NULL);
delete disallow_heap_allocation_;
disallow_heap_allocation_ = NULL;
#endif // DEBUG
}


@@ -1977,56 +1986,6 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
}


static bool ObjectToInt32(Object* obj, int32_t* value) {
if (obj->IsSmi()) {
*value = Smi::cast(obj)->value();
return true;
}

if (obj->IsHeapNumber()) {
double num = HeapNumber::cast(obj)->value();
if (FastI2D(FastD2I(num)) != num) {
if (FLAG_trace_osr) {
PrintF("**** %g could not be converted to int32 ****\n",
HeapNumber::cast(obj)->value());
}
return false;
}

*value = FastD2I(num);
return true;
}

return false;
}


static bool ObjectToUint32(Object* obj, uint32_t* value) {
if (obj->IsSmi()) {
if (Smi::cast(obj)->value() < 0) return false;

*value = static_cast<uint32_t>(Smi::cast(obj)->value());
return true;
}

if (obj->IsHeapNumber()) {
double num = HeapNumber::cast(obj)->value();
if ((num < 0) || (FastUI2D(FastD2UI(num)) != num)) {
if (FLAG_trace_osr) {
PrintF("**** %g could not be converted to uint32 ****\n",
HeapNumber::cast(obj)->value());
}
return false;
}

*value = FastD2UI(num);
return true;
}

return false;
}


bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
int* input_offset) {
disasm::NameConverter converter;
@@ -2070,7 +2029,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,

case Translation::INT32_REGISTER: {
int32_t int32_value = 0;
if (!ObjectToInt32(input_object, &int32_value)) return false;
if (!input_object->ToInt32(&int32_value)) return false;

int output_reg = iterator->Next();
if (FLAG_trace_osr) {
@@ -2085,7 +2044,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,

case Translation::UINT32_REGISTER: {
uint32_t uint32_value = 0;
if (!ObjectToUint32(input_object, &uint32_value)) return false;
if (!input_object->ToUint32(&uint32_value)) return false;

int output_reg = iterator->Next();
if (FLAG_trace_osr) {
@@ -2132,7 +2091,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,

case Translation::INT32_STACK_SLOT: {
int32_t int32_value = 0;
if (!ObjectToInt32(input_object, &int32_value)) return false;
if (!input_object->ToInt32(&int32_value)) return false;

int output_index = iterator->Next();
unsigned output_offset =
@@ -2149,7 +2108,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,

case Translation::UINT32_STACK_SLOT: {
uint32_t uint32_value = 0;
if (!ObjectToUint32(input_object, &uint32_value)) return false;
if (!input_object->ToUint32(&uint32_value)) return false;

int output_index = iterator->Next();
unsigned output_offset =
@@ -2750,7 +2709,6 @@ DeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) {
code_ = Handle<Code>::cast(global_handles->Create(code));
global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()),
this,
NULL,
Deoptimizer::HandleWeakDeoptimizedCode);
}

@@ -2855,7 +2813,7 @@ Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments(
JavaScriptFrame* frame,
int inlined_jsframe_index,
int formal_parameter_count) {
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
int deopt_index = Safepoint::kNoDeoptimizationIndex;
DeoptimizationInputData* data =
static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
@@ -38,6 +38,24 @@
namespace v8 {
namespace internal {


static inline double read_double_value(Address p) {
#ifdef V8_HOST_CAN_READ_UNALIGNED
return Memory::double_at(p);
#else // V8_HOST_CAN_READ_UNALIGNED
// Prevent gcc from using load-double (mips ldc1) on (possibly)
// non-64-bit aligned address.
union conversion {
double d;
uint32_t u[2];
} c;
c.u[0] = *reinterpret_cast<uint32_t*>(p);
c.u[1] = *reinterpret_cast<uint32_t*>(p + 4);
return c.d;
#endif // V8_HOST_CAN_READ_UNALIGNED
}


class FrameDescription;
class TranslationIterator;
class DeoptimizingCodeListNode;
@@ -385,7 +403,7 @@ class Deoptimizer : public Malloced {

// Weak handle callback for deoptimizing code objects.
static void HandleWeakDeoptimizedCode(v8::Isolate* isolate,
v8::Persistent<v8::Value> obj,
v8::Persistent<v8::Value>* obj,
void* data);

// Deoptimize function assuming that function->next_function_link() points
@@ -431,6 +449,9 @@ class Deoptimizer : public Malloced {
List<Object*> deferred_arguments_objects_values_;
List<ArgumentsObjectMaterializationDescriptor> deferred_arguments_objects_;
List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
#ifdef DEBUG
DisallowHeapAllocation* disallow_heap_allocation_;
#endif // DEBUG

bool trace_;

@@ -476,19 +497,7 @@ class FrameDescription {

double GetDoubleFrameSlot(unsigned offset) {
intptr_t* ptr = GetFrameSlotPointer(offset);
#if V8_TARGET_ARCH_MIPS
// Prevent gcc from using load-double (mips ldc1) on (possibly)
// non-64-bit aligned double. Uses two lwc1 instructions.
union conversion {
double d;
uint32_t u[2];
} c;
c.u[0] = *reinterpret_cast<uint32_t*>(ptr);
c.u[1] = *(reinterpret_cast<uint32_t*>(ptr) + 1);
return c.d;
#else
return *reinterpret_cast<double*>(ptr);
#endif
return read_double_value(reinterpret_cast<Address>(ptr));
}

void SetFrameSlot(unsigned offset, intptr_t value) {
@@ -818,7 +827,7 @@ class SlotRef BASE_EMBEDDED {
}

case DOUBLE: {
double value = Memory::double_at(addr_);
double value = read_double_value(addr_);
return isolate->factory()->NewNumber(value);
}

@@ -115,8 +115,8 @@ static int DecodeIt(Isolate* isolate,
const V8NameConverter& converter,
byte* begin,
byte* end) {
NoHandleAllocation ha(isolate);
AssertNoAllocation no_alloc;
SealHandleScope shs(isolate);
DisallowHeapAllocation no_alloc;
ExternalReferenceEncoder ref_encoder;
Heap* heap = HEAP;

@@ -155,7 +155,7 @@ static void CopyObjectToObjectElements(FixedArrayBase* from_base,
uint32_t to_start,
int raw_copy_size) {
ASSERT(to_base->map() != HEAP->fixed_cow_array_map());
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;
int copy_size = raw_copy_size;
if (raw_copy_size < 0) {
ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
@@ -204,7 +204,7 @@ static void CopyDictionaryToObjectElements(FixedArrayBase* from_base,
uint32_t to_start,
int raw_copy_size) {
SeededNumberDictionary* from = SeededNumberDictionary::cast(from_base);
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;
int copy_size = raw_copy_size;
Heap* heap = from->GetHeap();
if (raw_copy_size < 0) {
@@ -840,7 +840,7 @@ class ElementsAccessorBase : public ElementsAccessor {

// Fill in the content
{
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len0; i++) {
Object* e = to->get(i);
@@ -2044,7 +2044,7 @@ MUST_USE_RESULT MaybeObject* ArrayConstructInitializeElements(
}
case FAST_HOLEY_ELEMENTS:
case FAST_ELEMENTS: {
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
FixedArray* object_elms = FixedArray::cast(elms);
for (int index = 0; index < number_of_elements; index++) {
@@ -107,7 +107,7 @@ static Handle<Object> Invoke(bool is_construct,
// Save and restore context around invocation and block the
// allocation of handles without explicit handle scopes.
SaveContext save(isolate);
NoHandleAllocation na(isolate);
SealHandleScope shs(isolate);
JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());

// Call the function through the right JS entry stub.
@@ -641,7 +641,8 @@ Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {


Handle<Object> Execution::NewDate(double time, bool* exc) {
Handle<Object> time_obj = FACTORY->NewNumber(time);
Isolate* isolate = Isolate::Current();
Handle<Object> time_obj = isolate->factory()->NewNumber(time);
RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
}

@@ -72,26 +72,29 @@ v8::Handle<v8::FunctionTemplate> ExternalizeStringExtension::GetNativeFunction(
}


v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
const v8::Arguments& args) {
void ExternalizeStringExtension::Externalize(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() < 1 || !args[0]->IsString()) {
return v8::ThrowException(v8::String::New(
v8::ThrowException(v8::String::New(
"First parameter to externalizeString() must be a string."));
return;
}
bool force_two_byte = false;
if (args.Length() >= 2) {
if (args[1]->IsBoolean()) {
force_two_byte = args[1]->BooleanValue();
} else {
return v8::ThrowException(v8::String::New(
"Second parameter to externalizeString() must be a boolean."));
v8::ThrowException(v8::String::New(
"Second parameter to externalizeString() must be a boolean."));
return;
}
}
bool result = false;
Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
if (string->IsExternalString()) {
return v8::ThrowException(v8::String::New(
v8::ThrowException(v8::String::New(
"externalizeString() can't externalize twice."));
return;
}
if (string->IsOneByteRepresentation() && !force_two_byte) {
uint8_t* data = new uint8_t[string->length()];
@@ -115,21 +118,22 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
if (!result) delete resource;
}
if (!result) {
return v8::ThrowException(v8::String::New("externalizeString() failed."));
v8::ThrowException(v8::String::New("externalizeString() failed."));
return;
}
return v8::Undefined();
}


v8::Handle<v8::Value> ExternalizeStringExtension::IsAscii(
const v8::Arguments& args) {
void ExternalizeStringExtension::IsAscii(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1 || !args[0]->IsString()) {
return v8::ThrowException(v8::String::New(
v8::ThrowException(v8::String::New(
"isAsciiString() requires a single string argument."));
return;
}
return
Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation() ?
v8::True() : v8::False();
bool is_one_byte =
Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation();
args.GetReturnValue().Set(is_one_byte);
}


@@ -38,8 +38,8 @@ class ExternalizeStringExtension : public v8::Extension {
ExternalizeStringExtension() : v8::Extension("v8/externalize", kSource) {}
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
v8::Handle<v8::String> name);
static v8::Handle<v8::Value> Externalize(const v8::Arguments& args);
static v8::Handle<v8::Value> IsAscii(const v8::Arguments& args);
static void Externalize(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsAscii(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Register();
private:
static const char* const kSource;
@@ -38,13 +38,12 @@ v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
}


v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
void GCExtension::GC(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args[0]->BooleanValue()) {
HEAP->CollectGarbage(NEW_SPACE, "gc extension");
} else {
HEAP->CollectAllGarbage(Heap::kNoGCFlags, "gc extension");
}
return v8::Undefined();
}


@@ -38,7 +38,7 @@ class GCExtension : public v8::Extension {
explicit GCExtension(const char* source) : v8::Extension("v8/gc", source) {}
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
v8::Handle<v8::String> name);
static v8::Handle<v8::Value> GC(const v8::Arguments& args);
static void GC(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Register();
};

@@ -58,8 +58,8 @@ static void AddNumber(v8::Local<v8::Object> object,
}


v8::Handle<v8::Value> StatisticsExtension::GetCounters(
const v8::Arguments& args) {
void StatisticsExtension::GetCounters(
const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = Isolate::Current();
Heap* heap = isolate->heap();

@@ -141,7 +141,7 @@ v8::Handle<v8::Value> StatisticsExtension::GetCounters(
"lo_space_commited_bytes");
AddNumber(result, heap->amount_of_external_allocated_memory(),
"amount_of_external_allocated_memory");
return result;
args.GetReturnValue().Set(result);
}


@@ -38,7 +38,7 @@ class StatisticsExtension : public v8::Extension {
StatisticsExtension() : v8::Extension("v8/statistics", kSource) {}
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
v8::Handle<v8::String> name);
static v8::Handle<v8::Value> GetCounters(const v8::Arguments& args);
static void GetCounters(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Register();
private:
static const char* const kSource;
@@ -41,6 +41,14 @@ namespace v8 {
namespace internal {


Handle<Box> Factory::NewBox(Handle<Object> value, PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateBox(*value, pretenure),
Box);
}


Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
ASSERT(0 <= size);
CALL_HEAP_FUNCTION(
@@ -476,8 +484,7 @@ Handle<ExternalArray> Factory::NewExternalArray(int length,

Handle<JSGlobalPropertyCell> Factory::NewJSGlobalPropertyCell(
Handle<Object> value) {
ALLOW_HANDLE_DEREF(isolate(),
"converting a handle into a global property cell");
AllowDeferredHandleDereference convert_to_cell;
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateJSGlobalPropertyCell(*value),
@@ -677,9 +684,9 @@ Handle<JSObject> Factory::NewNeanderObject() {
}


Handle<Object> Factory::NewTypeError(const char* type,
Handle<Object> Factory::NewTypeError(const char* message,
Vector< Handle<Object> > args) {
return NewError("MakeTypeError", type, args);
return NewError("MakeTypeError", message, args);
}


@@ -688,9 +695,9 @@ Handle<Object> Factory::NewTypeError(Handle<String> message) {
}


Handle<Object> Factory::NewRangeError(const char* type,
Handle<Object> Factory::NewRangeError(const char* message,
Vector< Handle<Object> > args) {
return NewError("MakeRangeError", type, args);
return NewError("MakeRangeError", message, args);
}


@@ -699,8 +706,9 @@ Handle<Object> Factory::NewRangeError(Handle<String> message) {
}


Handle<Object> Factory::NewSyntaxError(const char* type, Handle<JSArray> args) {
return NewError("MakeSyntaxError", type, args);
Handle<Object> Factory::NewSyntaxError(const char* message,
Handle<JSArray> args) {
return NewError("MakeSyntaxError", message, args);
}


@@ -709,9 +717,9 @@ Handle<Object> Factory::NewSyntaxError(Handle<String> message) {
}


Handle<Object> Factory::NewReferenceError(const char* type,
Handle<Object> Factory::NewReferenceError(const char* message,
Vector< Handle<Object> > args) {
return NewError("MakeReferenceError", type, args);
return NewError("MakeReferenceError", message, args);
}


@@ -721,7 +729,7 @@ Handle<Object> Factory::NewReferenceError(Handle<String> message) {


Handle<Object> Factory::NewError(const char* maker,
const char* type,
const char* message,
Vector< Handle<Object> > args) {
// Instantiate a closeable HandleScope for EscapeFrom.
v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate()));
@@ -730,33 +738,33 @@ Handle<Object> Factory::NewError(const char* maker,
array->set(i, *args[i]);
}
Handle<JSArray> object = NewJSArrayWithElements(array);
Handle<Object> result = NewError(maker, type, object);
Handle<Object> result = NewError(maker, message, object);
return result.EscapeFrom(&scope);
}


Handle<Object> Factory::NewEvalError(const char* type,
Handle<Object> Factory::NewEvalError(const char* message,
Vector< Handle<Object> > args) {
return NewError("MakeEvalError", type, args);
return NewError("MakeEvalError", message, args);
}


Handle<Object> Factory::NewError(const char* type,
Handle<Object> Factory::NewError(const char* message,
Vector< Handle<Object> > args) {
return NewError("MakeError", type, args);
return NewError("MakeError", message, args);
}


Handle<String> Factory::EmergencyNewError(const char* type,
Handle<String> Factory::EmergencyNewError(const char* message,
Handle<JSArray> args) {
const int kBufferSize = 1000;
char buffer[kBufferSize];
size_t space = kBufferSize;
char* p = &buffer[0];

Vector<char> v(buffer, kBufferSize);
OS::StrNCpy(v, type, space);
space -= Min(space, strlen(type));
OS::StrNCpy(v, message, space);
space -= Min(space, strlen(message));
p = &buffer[kBufferSize] - space;

for (unsigned i = 0; i < ARRAY_SIZE(args); i++) {
@@ -785,7 +793,7 @@ Handle<String> Factory::EmergencyNewError(const char* type,


Handle<Object> Factory::NewError(const char* maker,
const char* type,
const char* message,
Handle<JSArray> args) {
Handle<String> make_str = InternalizeUtf8String(maker);
Handle<Object> fun_obj(
@@ -794,11 +802,11 @@ Handle<Object> Factory::NewError(const char* maker,
// If the builtins haven't been properly configured yet this error
// constructor may not have been defined. Bail out.
if (!fun_obj->IsJSFunction()) {
return EmergencyNewError(type, args);
return EmergencyNewError(message, args);
}
Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj);
Handle<Object> type_obj = InternalizeUtf8String(type);
Handle<Object> argv[] = { type_obj, args };
Handle<Object> message_obj = InternalizeUtf8String(message);
Handle<Object> argv[] = { message_obj, args };

// Invoke the JavaScript factory method. If an exception is thrown while
// running the factory method, use the exception as the result.
@@ -39,6 +39,11 @@ namespace internal {

class Factory {
public:
// Allocate a new boxed value.
Handle<Box> NewBox(
Handle<Object> value,
PretenureFlag pretenure = NOT_TENURED);

// Allocate a new uninitialized fixed array.
Handle<FixedArray> NewFixedArray(
int size,
@@ -369,33 +374,33 @@ class Factory {

// Interface for creating error objects.

Handle<Object> NewError(const char* maker, const char* type,
Handle<Object> NewError(const char* maker, const char* message,
Handle<JSArray> args);
Handle<String> EmergencyNewError(const char* type, Handle<JSArray> args);
Handle<Object> NewError(const char* maker, const char* type,
Handle<String> EmergencyNewError(const char* message, Handle<JSArray> args);
Handle<Object> NewError(const char* maker, const char* message,
Vector< Handle<Object> > args);
Handle<Object> NewError(const char* type,
Handle<Object> NewError(const char* message,
Vector< Handle<Object> > args);
Handle<Object> NewError(Handle<String> message);
Handle<Object> NewError(const char* constructor,
Handle<String> message);

Handle<Object> NewTypeError(const char* type,
Handle<Object> NewTypeError(const char* message,
Vector< Handle<Object> > args);
Handle<Object> NewTypeError(Handle<String> message);

Handle<Object> NewRangeError(const char* type,
Handle<Object> NewRangeError(const char* message,
Vector< Handle<Object> > args);
Handle<Object> NewRangeError(Handle<String> message);

Handle<Object> NewSyntaxError(const char* type, Handle<JSArray> args);
Handle<Object> NewSyntaxError(const char* message, Handle<JSArray> args);
Handle<Object> NewSyntaxError(Handle<String> message);

Handle<Object> NewReferenceError(const char* type,
Handle<Object> NewReferenceError(const char* message,
Vector< Handle<Object> > args);
Handle<Object> NewReferenceError(Handle<String> message);

Handle<Object> NewEvalError(const char* type,
Handle<Object> NewEvalError(const char* message,
Vector< Handle<Object> > args);


@@ -170,14 +170,17 @@ DEFINE_bool(harmony_array_buffer, false,
"enable harmony array buffer")
DEFINE_implication(harmony_typed_arrays, harmony_array_buffer)
DEFINE_bool(harmony_generators, false, "enable harmony generators")
DEFINE_bool(harmony_iteration, false, "enable harmony iteration (for-of)")
DEFINE_bool(harmony, false, "enable all harmony features (except typeof)")
DEFINE_implication(harmony, harmony_scoping)
DEFINE_implication(harmony, harmony_modules)
DEFINE_implication(harmony, harmony_symbols)
DEFINE_implication(harmony, harmony_proxies)
DEFINE_implication(harmony, harmony_collections)
DEFINE_implication(harmony, harmony_observation)
DEFINE_implication(harmony, harmony_generators)
// TODO(wingo): Re-enable when GC bug that appeared in r15060 is gone.
// DEFINE_implication(harmony, harmony_generators)
DEFINE_implication(harmony, harmony_iteration)
DEFINE_implication(harmony_modules, harmony_scoping)
DEFINE_implication(harmony_observation, harmony_collections)
// TODO[dslomov] add harmony => harmony_typed_arrays
@@ -192,12 +195,17 @@ DEFINE_bool(compiled_keyed_stores, true, "use optimizing compiler to "
DEFINE_bool(clever_optimizations,
true,
"Optimize object size, Array shift, DOM strings and string +")
DEFINE_bool(pretenure_literals, true, "allocate literals in old space")
DEFINE_bool(pretenuring, true, "allocate objects in old space")
// TODO(hpayer): We will remove this flag as soon as we have pretenuring
// support for specific allocation sites.
DEFINE_bool(pretenuring_call_new, false, "pretenure call new")
DEFINE_bool(track_fields, true, "track fields with only smi values")
DEFINE_bool(track_double_fields, true, "track fields with double values")
DEFINE_bool(track_heap_object_fields, true, "track fields with heap values")
DEFINE_bool(track_computed_fields, true, "track computed boilerplate fields")
DEFINE_implication(track_double_fields, track_fields)
DEFINE_implication(track_heap_object_fields, track_fields)
DEFINE_implication(track_computed_fields, track_fields)

// Flags for data representation optimizations
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
@@ -251,14 +259,16 @@ DEFINE_bool(array_bounds_checks_elimination, true,
"perform array bounds checks elimination")
DEFINE_bool(array_index_dehoisting, true,
"perform array index dehoisting")
DEFINE_bool(analyze_environment_liveness, true,
"analyze liveness of environment slots and zap dead values")
DEFINE_bool(dead_code_elimination, true, "use dead code elimination")
DEFINE_bool(fold_constants, true, "use constant folding")
DEFINE_bool(trace_dead_code_elimination, false, "trace dead code elimination")
DEFINE_bool(unreachable_code_elimination, false,
"eliminate unreachable code (hidden behind soft deopts)")
DEFINE_bool(track_allocation_sites, true,
"Use allocation site info to reduce transitions")
DEFINE_bool(optimize_constructed_arrays, false,
DEFINE_bool(optimize_constructed_arrays, true,
"Use allocation site info on constructed arrays")
DEFINE_bool(trace_osr, false, "trace on-stack replacement")
DEFINE_int(stress_runs, 0, "number of stress runs")
@@ -377,6 +387,8 @@ DEFINE_bool(stack_trace_on_abort, true,
"print a stack trace if an assertion failure occurs")

// codegen-ia32.cc / codegen-arm.cc
DEFINE_bool(trace_codegen, false,
"print name of functions for which code is generated")
DEFINE_bool(trace, false, "trace function calls")
DEFINE_bool(mask_constants_with_cookie,
true,
@@ -636,8 +648,6 @@ DEFINE_bool(enable_slow_asserts, false,
"enable asserts that are slow to execute")

// codegen-ia32.cc / codegen-arm.cc
DEFINE_bool(trace_codegen, false,
"print name of functions for which code is generated")
DEFINE_bool(print_source, false, "pretty print source code")
DEFINE_bool(print_builtin_source, false,
"pretty print source code for builtins")
@@ -777,7 +777,7 @@ void JavaScriptFrame::PrintTop(Isolate* isolate,
bool print_line_number) {
// constructor calls
HandleScope scope(isolate);
AssertNoAllocation no_allocation;
DisallowHeapAllocation no_allocation;
JavaScriptFrameIterator it(isolate);
while (!it.done()) {
if (it.frame()->is_java_script()) {
@@ -163,6 +163,12 @@ void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
}


void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
// For-of is breakable because of the next() call.
is_breakable_ = true;
}


void BreakableStatementChecker::VisitTryCatchStatement(
TryCatchStatement* stmt) {
// Mark try catch as breakable to avoid adding a break slot in front of it.
@@ -304,10 +310,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
int len = String::cast(script->source())->length();
isolate->counters()->total_full_codegen_source_size()->Increment(len);
}
if (FLAG_trace_codegen) {
PrintF("Full Compiler - ");
}
CodeGenerator::MakeCodePrologue(info);
CodeGenerator::MakeCodePrologue(info, "full");
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
#ifdef ENABLE_GDB_JIT_INTERFACE
@@ -923,10 +926,10 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
}


void FullCodeGenerator::EmitGeneratorSend(CallRuntime* expr) {
void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT(args->length() == 2);
EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::SEND);
EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT);
}


@@ -491,6 +491,11 @@ class FullCodeGenerator: public AstVisitor {
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
#undef EMIT_INLINE_RUNTIME_CALL

void EmitSeqStringSetCharCheck(Register string,
Register index,
Register value,
uint32_t encoding_mask);

// Platform-specific code for resuming generators.
void EmitGeneratorResume(Expression *generator,
Expression *value,
@@ -2062,7 +2062,7 @@ void GDBJITInterface::AddCode(const char* name,
if (!FLAG_gdbjit) return;

ScopedLock lock(mutex.Pointer());
AssertNoAllocation no_gc;
DisallowHeapAllocation no_gc;

HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
@@ -34,26 +34,16 @@
// ----------------------------------------------------------------------------


// TODO(wingo): Give link to specification. For now, the following diagram is
// the spec:
// http://wiki.ecmascript.org/lib/exe/fetch.php?cache=cache&media=harmony:es6_generator_object_model_3-29-13.png
// Generator functions and objects are specified by ES6, sections 15.19.3 and
// 15.19.4.

function GeneratorObjectNext() {
function GeneratorObjectNext(value) {
if (!IS_GENERATOR(this)) {
throw MakeTypeError('incompatible_method_receiver',
['[Generator].prototype.next', this]);
}

return %_GeneratorSend(this, void 0);
}

function GeneratorObjectSend(value) {
if (!IS_GENERATOR(this)) {
throw MakeTypeError('incompatible_method_receiver',
['[Generator].prototype.send', this]);
}

return %_GeneratorSend(this, value);
return %_GeneratorNext(this, value);
}

function GeneratorObjectThrow(exn) {
@@ -71,7 +61,6 @@ function SetUpGenerators() {
InstallFunctions(GeneratorObjectPrototype,
DONT_ENUM | DONT_DELETE | READ_ONLY,
["next", GeneratorObjectNext,
"send", GeneratorObjectSend,
"throw", GeneratorObjectThrow]);
%SetProperty(GeneratorObjectPrototype, "constructor",
GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY);
@@ -25,9 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// TODO(dcarney): remove
#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT

#include "v8.h"

#include "api.h"
@@ -92,7 +89,7 @@ class GlobalHandles::Node {
set_partially_dependent(false);
set_in_new_space_list(false);
parameter_or_next_free_.next_free = NULL;
near_death_callback_ = NULL;
weak_reference_callback_ = NULL;
}
#endif

@@ -105,19 +102,19 @@ class GlobalHandles::Node {
*first_free = this;
}

void Acquire(Object* object, GlobalHandles* global_handles) {
void Acquire(Object* object) {
ASSERT(state() == FREE);
object_ = object;
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
set_independent(false);
set_partially_dependent(false);
set_state(NORMAL);
parameter_or_next_free_.parameter = NULL;
near_death_callback_ = NULL;
IncreaseBlockUses(global_handles);
weak_reference_callback_ = NULL;
IncreaseBlockUses();
}

void Release(GlobalHandles* global_handles) {
void Release() {
ASSERT(state() != FREE);
set_state(FREE);
#ifdef ENABLE_EXTRA_CHECKS
@@ -126,11 +123,9 @@ class GlobalHandles::Node {
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
set_independent(false);
set_partially_dependent(false);
near_death_callback_ = NULL;
weak_reference_callback_ = NULL;
#endif
parameter_or_next_free_.next_free = global_handles->first_free_;
global_handles->first_free_ = this;
DecreaseBlockUses(global_handles);
DecreaseBlockUses();
}

// Object slot accessors.
@@ -201,9 +196,9 @@ class GlobalHandles::Node {
set_independent(true);
}

void MarkPartiallyDependent(GlobalHandles* global_handles) {
void MarkPartiallyDependent() {
ASSERT(state() != FREE);
if (global_handles->isolate()->heap()->InNewSpace(object_)) {
if (GetGlobalHandles()->isolate()->heap()->InNewSpace(object_)) {
set_partially_dependent(true);
}
}
@@ -233,41 +228,31 @@ class GlobalHandles::Node {
parameter_or_next_free_.next_free = value;
}

void MakeWeak(GlobalHandles* global_handles,
void* parameter,
RevivableCallback weak_reference_callback,
NearDeathCallback near_death_callback) {
void MakeWeak(void* parameter,
RevivableCallback weak_reference_callback) {
ASSERT(state() != FREE);
set_state(WEAK);
set_parameter(parameter);
if (weak_reference_callback != NULL) {
flags_ = IsWeakCallback::update(flags_, true);
near_death_callback_ =
reinterpret_cast<NearDeathCallback>(weak_reference_callback);
} else {
flags_ = IsWeakCallback::update(flags_, false);
near_death_callback_ = near_death_callback;
}
weak_reference_callback_ = weak_reference_callback;
}

void ClearWeakness(GlobalHandles* global_handles) {
void ClearWeakness() {
ASSERT(state() != FREE);
set_state(NORMAL);
set_parameter(NULL);
}

bool PostGarbageCollectionProcessing(Isolate* isolate,
GlobalHandles* global_handles) {
bool PostGarbageCollectionProcessing(Isolate* isolate) {
if (state() != Node::PENDING) return false;
if (near_death_callback_ == NULL) {
Release(global_handles);
if (weak_reference_callback_ == NULL) {
Release();
return false;
}
void* par = parameter();
set_state(NEAR_DEATH);
set_parameter(NULL);

v8::Persistent<v8::Value> object = ToApi<v8::Value>(handle());
Object** object = location();
{
// Check that we are not passing a finalized external string to
// the callback.
@@ -277,19 +262,9 @@ class GlobalHandles::Node {
ExternalTwoByteString::cast(object_)->resource() != NULL);
// Leaving V8.
VMState<EXTERNAL> state(isolate);
if (near_death_callback_ != NULL) {
if (IsWeakCallback::decode(flags_)) {
RevivableCallback callback =
reinterpret_cast<RevivableCallback>(near_death_callback_);
callback(reinterpret_cast<v8::Isolate*>(isolate),
&object,
par);
} else {
near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate),
object,
weak_reference_callback_(reinterpret_cast<v8::Isolate*>(isolate),
reinterpret_cast<Persistent<Value>*>(&object),
par);
}
}
}
// Absence of explicit cleanup or revival of weak handle
// in most of the cases would lead to memory leak.
@@ -299,8 +274,9 @@ class GlobalHandles::Node {

private:
inline NodeBlock* FindBlock();
inline void IncreaseBlockUses(GlobalHandles* global_handles);
inline void DecreaseBlockUses(GlobalHandles* global_handles);
inline GlobalHandles* GetGlobalHandles();
inline void IncreaseBlockUses();
inline void DecreaseBlockUses();

// Storage for object pointer.
// Placed first to avoid offset computation.
@@ -321,12 +297,11 @@ class GlobalHandles::Node {
class IsIndependent: public BitField<bool, 4, 1> {};
class IsPartiallyDependent: public BitField<bool, 5, 1> {};
class IsInNewSpaceList: public BitField<bool, 6, 1> {};
class IsWeakCallback: public BitField<bool, 7, 1> {};

uint8_t flags_;

// Handle specific callback - might be a weak reference in disguise.
NearDeathCallback near_death_callback_;
RevivableCallback weak_reference_callback_;

// Provided data for callback. In FREE state, this is used for
// the free list link.
@@ -343,8 +318,12 @@ class GlobalHandles::NodeBlock {
public:
static const int kSize = 256;

explicit NodeBlock(NodeBlock* next)
: next_(next), used_nodes_(0), next_used_(NULL), prev_used_(NULL) {}
explicit NodeBlock(GlobalHandles* global_handles, NodeBlock* next)
: next_(next),
used_nodes_(0),
next_used_(NULL),
prev_used_(NULL),
global_handles_(global_handles) {}

void PutNodesOnFreeList(Node** first_free) {
for (int i = kSize - 1; i >= 0; --i) {
@@ -357,29 +336,31 @@ class GlobalHandles::NodeBlock {
return &nodes_[index];
}

void IncreaseUses(GlobalHandles* global_handles) {
void IncreaseUses() {
ASSERT(used_nodes_ < kSize);
if (used_nodes_++ == 0) {
NodeBlock* old_first = global_handles->first_used_block_;
global_handles->first_used_block_ = this;
NodeBlock* old_first = global_handles_->first_used_block_;
global_handles_->first_used_block_ = this;
next_used_ = old_first;
prev_used_ = NULL;
if (old_first == NULL) return;
old_first->prev_used_ = this;
}
}

void DecreaseUses(GlobalHandles* global_handles) {
void DecreaseUses() {
ASSERT(used_nodes_ > 0);
if (--used_nodes_ == 0) {
if (next_used_ != NULL) next_used_->prev_used_ = prev_used_;
if (prev_used_ != NULL) prev_used_->next_used_ = next_used_;
if (this == global_handles->first_used_block_) {
global_handles->first_used_block_ = next_used_;
if (this == global_handles_->first_used_block_) {
global_handles_->first_used_block_ = next_used_;
}
}
}

GlobalHandles* global_handles() { return global_handles_; }

// Next block in the list of all blocks.
NodeBlock* next() const { return next_; }

@@ -393,9 +374,15 @@ class GlobalHandles::NodeBlock {
int used_nodes_;
NodeBlock* next_used_;
NodeBlock* prev_used_;
GlobalHandles* global_handles_;
};


GlobalHandles* GlobalHandles::Node::GetGlobalHandles() {
return FindBlock()->global_handles();
}


GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
intptr_t ptr = reinterpret_cast<intptr_t>(this);
ptr = ptr - index_ * sizeof(Node);
@@ -405,13 +392,23 @@ GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
}


void GlobalHandles::Node::IncreaseBlockUses(GlobalHandles* global_handles) {
FindBlock()->IncreaseUses(global_handles);
void GlobalHandles::Node::IncreaseBlockUses() {
NodeBlock* node_block = FindBlock();
node_block->IncreaseUses();
GlobalHandles* global_handles = node_block->global_handles();
global_handles->isolate()->counters()->global_handles()->Increment();
global_handles->number_of_global_handles_++;
}


void GlobalHandles::Node::DecreaseBlockUses(GlobalHandles* global_handles) {
FindBlock()->DecreaseUses(global_handles);
void GlobalHandles::Node::DecreaseBlockUses() {
NodeBlock* node_block = FindBlock();
GlobalHandles* global_handles = node_block->global_handles();
parameter_or_next_free_.next_free = global_handles->first_free_;
global_handles->first_free_ = this;
node_block->DecreaseUses();
global_handles->isolate()->counters()->global_handles()->Decrement();
global_handles->number_of_global_handles_--;
}


@@ -465,17 +462,15 @@ GlobalHandles::~GlobalHandles() {


Handle<Object> GlobalHandles::Create(Object* value) {
isolate_->counters()->global_handles()->Increment();
number_of_global_handles_++;
if (first_free_ == NULL) {
first_block_ = new NodeBlock(first_block_);
first_block_ = new NodeBlock(this, first_block_);
first_block_->PutNodesOnFreeList(&first_free_);
}
ASSERT(first_free_ != NULL);
// Take the first node in the free list.
Node* result = first_free_;
first_free_ = result->next_free();
result->Acquire(value, this);
result->Acquire(value);
if (isolate_->heap()->InNewSpace(value) &&
!result->is_in_new_space_list()) {
new_space_nodes_.Add(result);
@@ -486,27 +481,20 @@ Handle<Object> GlobalHandles::Create(Object* value) {


void GlobalHandles::Destroy(Object** location) {
isolate_->counters()->global_handles()->Decrement();
number_of_global_handles_--;
if (location == NULL) return;
Node::FromLocation(location)->Release(this);
if (location != NULL) Node::FromLocation(location)->Release();
}


void GlobalHandles::MakeWeak(Object** location,
void* parameter,
RevivableCallback weak_reference_callback,
NearDeathCallback near_death_callback) {
ASSERT((weak_reference_callback == NULL) != (near_death_callback == NULL));
Node::FromLocation(location)->MakeWeak(this,
parameter,
weak_reference_callback,
near_death_callback);
RevivableCallback weak_reference_callback) {
ASSERT(weak_reference_callback != NULL);
Node::FromLocation(location)->MakeWeak(parameter, weak_reference_callback);
}


void GlobalHandles::ClearWeakness(Object** location) {
Node::FromLocation(location)->ClearWeakness(this);
Node::FromLocation(location)->ClearWeakness();
}


@@ -516,7 +504,7 @@ void GlobalHandles::MarkIndependent(Object** location) {


void GlobalHandles::MarkPartiallyDependent(Object** location) {
Node::FromLocation(location)->MarkPartiallyDependent(this);
Node::FromLocation(location)->MarkPartiallyDependent();
}


@@ -653,7 +641,7 @@ bool GlobalHandles::PostGarbageCollectionProcessing(
continue;
}
node->clear_partially_dependent();
if (node->PostGarbageCollectionProcessing(isolate_, this)) {
if (node->PostGarbageCollectionProcessing(isolate_)) {
if (initial_post_gc_processing_count != post_gc_processing_count_) {
// Weak callback triggered another GC and another round of
// PostGarbageCollection processing. The current node might
@@ -669,7 +657,7 @@ bool GlobalHandles::PostGarbageCollectionProcessing(
} else {
for (NodeIterator it(this); !it.done(); it.Advance()) {
it.node()->clear_partially_dependent();
if (it.node()->PostGarbageCollectionProcessing(isolate_, this)) {
if (it.node()->PostGarbageCollectionProcessing(isolate_)) {
if (initial_post_gc_processing_count != post_gc_processing_count_) {
// See the comment above.
return next_gc_likely_to_collect_more;