diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index a81dedd45d..fecc591320 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,13 @@ +2011-12-21: Version 3.8.2 + + Add max optimization flag to v8 gyp build to ensure V8 is always built + fully optimized in Chrome. + + MIPS: Bring MIPS to parity with other platforms. + + Optimizations and stability improvements on all platforms. + + 2011-12-19: Version 3.8.1 Fixed GCC 4.7 warnings. Patch from Tobias Burnus. diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi index 9129d0170c..e191679769 100644 --- a/deps/v8/build/common.gypi +++ b/deps/v8/build/common.gypi @@ -84,6 +84,10 @@ # For a shared library build, results in "libv8-<(soname_version).so". 'soname_version%': '', + + # We want max optimization for the V8 build (if this is not set, chrome + # defaults to low optimization settings) + 'optimize': 'max', }, 'target_defaults': { 'conditions': [ diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 1ac152d6a7..643d0ebe60 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -1779,11 +1779,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { - LOperand* temp = TempRegister(); - LOperand* value = UseTempRegister(instr->value()); - LInstruction* result = new LStoreGlobalCell(value, temp); - if (instr->RequiresHoleCheck()) result = AssignEnvironment(result); - return result; + LOperand* value = UseRegister(instr->value()); + // Use a temp to check the value in the cell in the case where we perform + // a hole check. + return instr->RequiresHoleCheck() + ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister())) + : new LStoreGlobalCell(value, NULL); } diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index 628c3d1a59..703666c4a1 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -1242,6 +1242,8 @@ class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> { DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) + + LOperand* value() { return inputs_[0]; } }; diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index cdc464c322..4b68438300 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -2262,27 +2262,26 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { - Register value = ToRegister(instr->InputAt(0)); - Register scratch = scratch0(); - Register scratch2 = ToRegister(instr->TempAt(0)); + Register value = ToRegister(instr->value()); + Register cell = scratch0(); // Load the cell. - __ mov(scratch, Operand(Handle(instr->hydrogen()->cell()))); + __ mov(cell, Operand(instr->hydrogen()->cell())); // If the cell we are storing to contains the hole it could have // been deleted from the property dictionary. In that case, we need // to update the property details in the property dictionary to mark // it as no longer deleted. if (instr->hydrogen()->RequiresHoleCheck()) { - __ ldr(scratch2, - FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ cmp(scratch2, ip); + // We use a temp to check the payload (CompareRoot might clobber ip). + Register payload = ToRegister(instr->TempAt(0)); + __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); + __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); DeoptimizeIf(eq, instr->environment()); } // Store the value. - __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); + __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); // Cells are always rescanned, so no write barrier here. } diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index b66f448407..2de7b92f5e 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 Sun Microsystems Inc. +// Copyright (c) 1994-2006 Sun Microsystems Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index 7883481041..ab38502768 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -2124,26 +2124,20 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { - Register object = ToRegister(instr->TempAt(0)); - Register address = ToRegister(instr->TempAt(1)); - Register value = ToRegister(instr->InputAt(0)); - ASSERT(!value.is(object)); - Handle cell_handle(instr->hydrogen()->cell()); - - int offset = JSGlobalPropertyCell::kValueOffset; - __ mov(object, Immediate(cell_handle)); + Register value = ToRegister(instr->value()); + Handle cell_handle = instr->hydrogen()->cell(); // If the cell we are storing to contains the hole it could have // been deleted from the property dictionary. In that case, we need // to update the property details in the property dictionary to mark // it as no longer deleted. We deoptimize in that case. if (instr->hydrogen()->RequiresHoleCheck()) { - __ cmp(FieldOperand(object, offset), factory()->the_hole_value()); + __ cmp(Operand::Cell(cell_handle), factory()->the_hole_value()); DeoptimizeIf(equal, instr->environment()); } // Store the value. - __ mov(FieldOperand(object, offset), value); + __ mov(Operand::Cell(cell_handle), value); // Cells are always rescanned, so no write barrier here. } diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc index f364439f10..c50378514a 100644 --- a/deps/v8/src/ia32/lithium-ia32.cc +++ b/deps/v8/src/ia32/lithium-ia32.cc @@ -1856,9 +1856,7 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { LStoreGlobalCell* result = - new(zone()) LStoreGlobalCell(UseTempRegister(instr->value()), - TempRegister(), - TempRegister()); + new(zone()) LStoreGlobalCell(UseRegister(instr->value())); return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; } diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h index 7e126ff03c..cc3762d7ab 100644 --- a/deps/v8/src/ia32/lithium-ia32.h +++ b/deps/v8/src/ia32/lithium-ia32.h @@ -1269,16 +1269,16 @@ class LLoadGlobalGeneric: public LTemplateInstruction<1, 2, 0> { }; -class LStoreGlobalCell: public LTemplateInstruction<0, 1, 2> { +class LStoreGlobalCell: public LTemplateInstruction<0, 1, 0> { public: - explicit LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) { + explicit LStoreGlobalCell(LOperand* value) { inputs_[0] = value; - temps_[0] = temp1; - temps_[1] = temp2; } DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) + + LOperand* value() { return inputs_[0]; } }; diff --git a/deps/v8/src/mips/builtins-mips.cc b/deps/v8/src/mips/builtins-mips.cc index 98fd57de78..701450b814 100644 --- a/deps/v8/src/mips/builtins-mips.cc +++ b/deps/v8/src/mips/builtins-mips.cc @@ -400,13 +400,19 @@ static void ArrayNativeCode(MacroAssembler* masm, // sp[0]: last argument Label loop, entry; - __ Branch(&entry); + __ Branch(USE_DELAY_SLOT, &entry); + __ mov(t3, sp); __ bind(&loop); - __ pop(a2); + __ lw(a2, MemOperand(t3)); + __ Addu(t3, t3, kPointerSize); + if (FLAG_smi_only_arrays) { + __ JumpIfNotSmi(a2, call_generic_code); + } __ Addu(t1, t1, -kPointerSize); __ sw(a2, MemOperand(t1)); __ bind(&entry); __ Branch(&loop, lt, t0, Operand(t1)); + __ mov(sp, t3); // Remove caller arguments and receiver from the stack, setup return value and // return. diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc index eaef6ff40d..895b4c98ca 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/mips/lithium-codegen-mips.cc @@ -2141,26 +2141,26 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { - Register value = ToRegister(instr->InputAt(0)); - Register scratch = scratch0(); - Register scratch2 = ToRegister(instr->TempAt(0)); + Register value = ToRegister(instr->value()); + Register cell = scratch0(); // Load the cell. - __ li(scratch, Operand(Handle(instr->hydrogen()->cell()))); + __ li(cell, Operand(instr->hydrogen()->cell())); // If the cell we are storing to contains the hole it could have // been deleted from the property dictionary. In that case, we need // to update the property details in the property dictionary to mark // it as no longer deleted. if (instr->hydrogen()->RequiresHoleCheck()) { - __ lw(scratch2, - FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); + // We use a temp to check the payload. + Register payload = ToRegister(instr->TempAt(0)); + __ lw(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - DeoptimizeIf(eq, instr->environment(), scratch2, Operand(at)); + DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); } // Store the value. - __ sw(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); + __ sw(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); // Cells are always rescanned, so no write barrier here. } diff --git a/deps/v8/src/mips/lithium-mips.cc b/deps/v8/src/mips/lithium-mips.cc index f963ec9e3f..1040b28ff6 100644 --- a/deps/v8/src/mips/lithium-mips.cc +++ b/deps/v8/src/mips/lithium-mips.cc @@ -1782,11 +1782,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { - LOperand* temp = TempRegister(); - LOperand* value = UseTempRegister(instr->value()); - LInstruction* result = new LStoreGlobalCell(value, temp); - if (instr->RequiresHoleCheck()) result = AssignEnvironment(result); - return result; + LOperand* value = UseRegister(instr->value()); + // Use a temp to check the value in the cell in the case where we perform + // a hole check. + return instr->RequiresHoleCheck() + ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister())) + : new LStoreGlobalCell(value, NULL); } diff --git a/deps/v8/src/mips/lithium-mips.h b/deps/v8/src/mips/lithium-mips.h index efc5e274be..da59dd8b0c 100644 --- a/deps/v8/src/mips/lithium-mips.h +++ b/deps/v8/src/mips/lithium-mips.h @@ -1242,6 +1242,8 @@ class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> { DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) + + LOperand* value() { return inputs_[0]; } }; diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index b0e1a057da..544b210c0b 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -4326,12 +4326,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { LookupResult result(isolate); js_object->LocalLookupRealNamedProperty(*name, &result); - // To be compatible with safari we do not change the value on API objects - // in defineProperty. Firefox disagrees here, and actually changes the value. - if (result.IsProperty() && - (result.type() == CALLBACKS) && - result.GetCallbackObject()->IsAccessorInfo()) { - return isolate->heap()->undefined_value(); + // Special case for callback properties. + if (result.IsProperty() && result.type() == CALLBACKS) { + Object* callback = result.GetCallbackObject(); + // To be compatible with Safari we do not change the value on API objects + // in Object.defineProperty(). Firefox disagrees here, and actually changes + // the value. + if (callback->IsAccessorInfo()) { + return isolate->heap()->undefined_value(); + } + // Avoid redefining foreign callback as data property, just use the stored + // setter to update the value instead. + // TODO(mstarzinger): So far this only works if property attributes don't + // change, this should be fixed once we cleanup the underlying code. + if (callback->IsForeign() && result.GetAttributes() == attr) { + return js_object->SetPropertyWithCallback(callback, + *name, + *obj_value, + result.holder(), + kStrictMode); + } } // Take special care when attributes are different and there is already diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc old mode 100644 new mode 100755 diff --git a/deps/v8/src/type-info.cc b/deps/v8/src/type-info.cc index af8a8ae828..790d77cb19 100644 --- a/deps/v8/src/type-info.cc +++ b/deps/v8/src/type-info.cc @@ -85,7 +85,8 @@ bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { return code->is_keyed_load_stub() && code->ic_state() == MONOMORPHIC && Code::ExtractTypeFromFlags(code->flags()) == NORMAL && - code->FindFirstMap() != NULL; + code->FindFirstMap() != NULL && + !CanRetainOtherContext(code->FindFirstMap(), *global_context_); } return false; } @@ -111,7 +112,9 @@ bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) { Handle code = Handle::cast(map_or_code); return code->is_keyed_store_stub() && code->ic_state() == MONOMORPHIC && - Code::ExtractTypeFromFlags(code->flags()) == NORMAL; + Code::ExtractTypeFromFlags(code->flags()) == NORMAL && + code->FindFirstMap() != NULL && + !CanRetainOtherContext(code->FindFirstMap(), *global_context_); } return false; } @@ -144,7 +147,9 @@ Handle TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { Handle code = Handle::cast(map_or_code); Map* first_map = code->FindFirstMap(); ASSERT(first_map != NULL); - return Handle(first_map); + return CanRetainOtherContext(first_map, *global_context_) + ? Handle::null() + : Handle(first_map); } return Handle::cast(map_or_code); } @@ -155,7 +160,11 @@ Handle TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { Handle map_or_code = GetInfo(expr->id()); if (map_or_code->IsCode()) { Handle code = Handle::cast(map_or_code); - return Handle(code->FindFirstMap()); + Map* first_map = code->FindFirstMap(); + ASSERT(first_map != NULL); + return CanRetainOtherContext(first_map, *global_context_) + ? Handle::null() + : Handle(first_map); } return Handle::cast(map_or_code); } @@ -288,7 +297,11 @@ Handle TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { if (state != CompareIC::KNOWN_OBJECTS) { return Handle::null(); } - return Handle(code->FindFirstMap()); + Map* first_map = code->FindFirstMap(); + ASSERT(first_map != NULL); + return CanRetainOtherContext(first_map, *global_context_) + ? Handle::null() + : Handle(first_map); } @@ -451,20 +464,23 @@ void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, // retaining objects from different tabs in Chrome via optimized code. bool TypeFeedbackOracle::CanRetainOtherContext(Map* map, Context* global_context) { - Object* constructor = map->constructor(); - ASSERT(constructor != NULL); - while (!constructor->IsJSFunction()) { - // If the constructor is not null or a JSFunction, we have to - // conservatively assume that it may retain a global context. - if (!constructor->IsNull()) return true; - - // If both, constructor and prototype are null, we conclude - // that no global context will be retained by this map. - if (map->prototype()->IsNull()) return false; - - map = JSObject::cast(map->prototype())->map(); + Object* constructor = NULL; + while (!map->prototype()->IsNull()) { constructor = map->constructor(); + if (!constructor->IsNull()) { + // If the constructor is not null or a JSFunction, we have to + // conservatively assume that it may retain a global context. + if (!constructor->IsJSFunction()) return true; + // Check if the constructor directly references a foreign context. + if (CanRetainOtherContext(JSFunction::cast(constructor), + global_context)) { + return true; + } + } + map = HeapObject::cast(map->prototype())->map(); } + constructor = map->constructor(); + if (constructor->IsNull()) return false; JSFunction* function = JSFunction::cast(constructor); return CanRetainOtherContext(function, global_context); } @@ -498,7 +514,10 @@ void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id, RelocInfo* info = it.rinfo(); Object* object = info->target_object(); if (object->IsMap()) { - AddMapIfMissing(Handle(Map::cast(object)), types); + Map* map = Map::cast(object); + if (!CanRetainOtherContext(map, *global_context_)) { + AddMapIfMissing(Handle(map), types); + } } } } diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 79ea5e866b..bbd26a4af1 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -34,7 +34,7 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 3 #define MINOR_VERSION 8 -#define BUILD_NUMBER 1 +#define BUILD_NUMBER 2 #define PATCH_LEVEL 0 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc index a96d140d49..70f5874b5c 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.cc +++ b/deps/v8/src/x64/lithium-codegen-x64.cc @@ -2028,25 +2028,27 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { - Register object = ToRegister(instr->TempAt(0)); - Register address = ToRegister(instr->TempAt(1)); - Register value = ToRegister(instr->InputAt(0)); - ASSERT(!value.is(object)); - Handle cell_handle(instr->hydrogen()->cell()); - - __ movq(address, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); + Register value = ToRegister(instr->value()); + Handle cell_handle = instr->hydrogen()->cell(); // If the cell we are storing to contains the hole it could have // been deleted from the property dictionary. In that case, we need // to update the property details in the property dictionary to mark // it as no longer deleted. We deoptimize in that case. if (instr->hydrogen()->RequiresHoleCheck()) { - __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex); + // We have a temp because CompareRoot might clobber kScratchRegister. + Register cell = ToRegister(instr->TempAt(0)); + ASSERT(!value.is(cell)); + __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); + __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); DeoptimizeIf(equal, instr->environment()); + // Store the value. + __ movq(Operand(cell, 0), value); + } else { + // Store the value. + __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); + __ movq(Operand(kScratchRegister, 0), value); } - - // Store the value. - __ movq(Operand(address, 0), value); // Cells are always rescanned, so no write barrier here. } diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc index 7fa8a3999c..ac4d5f5d3e 100644 --- a/deps/v8/src/x64/lithium-x64.cc +++ b/deps/v8/src/x64/lithium-x64.cc @@ -1768,11 +1768,12 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { - LStoreGlobalCell* result = - new LStoreGlobalCell(UseTempRegister(instr->value()), - TempRegister(), - TempRegister()); - return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; + LOperand* value = UseRegister(instr->value()); + // Use a temp to avoid reloading the cell value address in the case where + // we perform a hole check. + return instr->RequiresHoleCheck() + ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister())) + : new LStoreGlobalCell(value, NULL); } diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h index 280d2358c4..c6fcfeb81e 100644 --- a/deps/v8/src/x64/lithium-x64.h +++ b/deps/v8/src/x64/lithium-x64.h @@ -1231,16 +1231,17 @@ class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> { }; -class LStoreGlobalCell: public LTemplateInstruction<0, 1, 2> { +class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> { public: - explicit LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) { + explicit LStoreGlobalCell(LOperand* value, LOperand* temp) { inputs_[0] = value; - temps_[0] = temp1; - temps_[1] = temp2; + temps_[0] = temp; } DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell") DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell) + + LOperand* value() { return inputs_[0]; } }; diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index 6d36aa6740..2de0afba17 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -52,10 +52,6 @@ test-profile-generator/RecordStackTraceAtStartProfiling: PASS || FAIL # We do not yet shrink weak maps after they have been emptied by the GC test-weakmaps/Shrinking: FAIL -# TODO(1823): Fails without snapshot. Temporarily disabled until fixed. -test-heap/LeakGlobalContextViaMap: SKIP -test-heap/LeakGlobalContextViaFunction: SKIP - ############################################################################## [ $arch == arm ] diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 0e09ee38e1..42b5789d4d 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -1333,6 +1333,7 @@ static int NumberOfGlobalObjects() { // Test that we don't embed maps from foreign contexts into // optimized code. TEST(LeakGlobalContextViaMap) { + i::FLAG_allow_natives_syntax = true; v8::HandleScope outer_scope; v8::Persistent ctx1 = v8::Context::New(); v8::Persistent ctx2 = v8::Context::New(); @@ -1349,7 +1350,8 @@ TEST(LeakGlobalContextViaMap) { ctx2->Global()->Set(v8_str("o"), v); v8::Local res = CompileRun( "function f() { return o.x; }" - "for (var i = 0; i < 1000000; ++i) f();" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" "f();"); CHECK_EQ(42, res->Int32Value()); ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); @@ -1368,6 +1370,7 @@ TEST(LeakGlobalContextViaMap) { // Test that we don't embed functions from foreign contexts into // optimized code. TEST(LeakGlobalContextViaFunction) { + i::FLAG_allow_natives_syntax = true; v8::HandleScope outer_scope; v8::Persistent ctx1 = v8::Context::New(); v8::Persistent ctx2 = v8::Context::New(); @@ -1384,7 +1387,8 @@ TEST(LeakGlobalContextViaFunction) { ctx2->Global()->Set(v8_str("o"), v); v8::Local res = CompileRun( "function f(x) { return x(); }" - "for (var i = 0; i < 1000000; ++i) f(o);" + "for (var i = 0; i < 10; ++i) f(o);" + "%OptimizeFunctionOnNextCall(f);" "f(o);"); CHECK_EQ(42, res->Int32Value()); ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); @@ -1398,3 +1402,77 @@ TEST(LeakGlobalContextViaFunction) { HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, NumberOfGlobalObjects()); } + + +TEST(LeakGlobalContextViaMapKeyed) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent ctx1 = v8::Context::New(); + v8::Persistent ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + + { + v8::HandleScope inner_scope; + CompileRun("var v = [42, 43]"); + v8::Local v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local res = CompileRun( + "function f() { return o[0]; }" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); + } + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(LeakGlobalContextViaMapProto) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent ctx1 = v8::Context::New(); + v8::Persistent ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + + { + v8::HandleScope inner_scope; + CompileRun("var v = { y: 42}"); + v8::Local v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local res = CompileRun( + "function f() {" + " var p = {x: 42};" + " p.__proto__ = o;" + " return p.x;" + "}" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); + } + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} diff --git a/deps/v8/test/mjsunit/regress/regress-1530.js b/deps/v8/test/mjsunit/regress/regress-1530.js new file mode 100644 index 0000000000..db2114450e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-1530.js @@ -0,0 +1,69 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// 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. + +// Test that redefining the 'prototype' property of a function object +// does actually set the internal value and does not screw up any +// shadowing between said property and the internal value. + +var f = function() {}; + +// Verify that normal assignment of 'prototype' property works properly +// and updates the internal value. +var x = { foo: 'bar' }; +f.prototype = x; +assertSame(f.prototype, x); +assertSame(f.prototype.foo, 'bar'); +assertSame(new f().foo, 'bar'); +assertSame(Object.getPrototypeOf(new f()), x); +assertSame(Object.getOwnPropertyDescriptor(f, 'prototype').value, x); + +// Verify that 'prototype' behaves like a data property when it comes to +// redefining with Object.defineProperty() and the internal value gets +// updated. +var y = { foo: 'baz' }; +Object.defineProperty(f, 'prototype', { value: y, writable: true }); +assertSame(f.prototype, y); +assertSame(f.prototype.foo, 'baz'); +assertSame(new f().foo, 'baz'); +assertSame(Object.getPrototypeOf(new f()), y); +assertSame(Object.getOwnPropertyDescriptor(f, 'prototype').value, y); + +// Verify that the previous redefinition didn't screw up callbacks and +// the internal value still gets updated. +var z = { foo: 'other' }; +f.prototype = z; +assertSame(f.prototype, z); +assertSame(f.prototype.foo, 'other'); +assertSame(new f().foo, 'other'); +assertSame(Object.getPrototypeOf(new f()), z); +assertSame(Object.getOwnPropertyDescriptor(f, 'prototype').value, z); + +// Verify that non-writability of other properties is respected. +assertThrows("Object.defineProperty(f, 'name', { value: {} })"); +assertThrows("Object.defineProperty(f, 'length', { value: {} })"); +assertThrows("Object.defineProperty(f, 'caller', { value: {} })"); +assertThrows("Object.defineProperty(f, 'arguments', { value: {} })"); diff --git a/deps/v8/test/test262/test262.status b/deps/v8/test/test262/test262.status index 5fa0ba8518..1da988efc1 100644 --- a/deps/v8/test/test262/test262.status +++ b/deps/v8/test/test262/test262.status @@ -39,9 +39,6 @@ S8.7_A5_T2: FAIL # V8 Bug: http://code.google.com/p/v8/issues/detail?id=1624 S10.4.2.1_A1: FAIL -# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1530 -S15.3.3.1_A4: FAIL - # V8 Bug: http://code.google.com/p/v8/issues/detail?id=1475 15.2.3.6-4-405: FAIL 15.2.3.6-4-410: FAIL diff --git a/deps/v8/tools/gc-nvp-trace-processor.py b/deps/v8/tools/gc-nvp-trace-processor.py index de3dc90bd4..fe5a7f361e 100755 --- a/deps/v8/tools/gc-nvp-trace-processor.py +++ b/deps/v8/tools/gc-nvp-trace-processor.py @@ -219,7 +219,7 @@ def other_scope(r): if r['gc'] == 's': # there is no 'other' scope for scavenging collections. return 0 - return r['pause'] - r['mark'] - r['sweep'] - r['compact'] - r['external'] + return r['pause'] - r['mark'] - r['sweep'] - r['external'] def scavenge_scope(r): if r['gc'] == 's': @@ -238,7 +238,6 @@ plots = [ Plot(Item('Scavenge', scavenge_scope, lc = 'green'), Item('Marking', 'mark', lc = 'purple'), Item('Sweep', 'sweep', lc = 'blue'), - Item('Compaction', 'compact', lc = 'red'), Item('External', 'external', lc = '#489D43'), Item('Other', other_scope, lc = 'grey'), Item('IGC Steps', 'stepstook', lc = '#FF6347')) @@ -250,7 +249,6 @@ plots = [ Plot(Item('Scavenge', scavenge_scope, lc = 'green'), Item('Marking', 'mark', lc = 'purple'), Item('Sweep', 'sweep', lc = 'blue'), - Item('Compaction', 'compact', lc = 'red'), Item('External', 'external', lc = '#489D43'), Item('Other', other_scope, lc = '#ADD8E6'), Item('External', 'external', lc = '#D3D3D3')) @@ -309,7 +307,6 @@ def process_trace(filename): trace = parse_gc_trace(filename) marksweeps = filter(lambda r: r['gc'] == 'ms', trace) - markcompacts = filter(lambda r: r['gc'] == 'mc', trace) scavenges = filter(lambda r: r['gc'] == 's', trace) globalgcs = filter(lambda r: r['gc'] != 's', trace) @@ -368,10 +365,8 @@ def process_trace(filename): stats(out, 'Total in GC', trace, 'pause') stats(out, 'Scavenge', scavenges, 'pause') stats(out, 'MarkSweep', marksweeps, 'pause') - stats(out, 'MarkCompact', markcompacts, 'pause') stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark') stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep') - stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact') stats(out, 'External', filter(lambda r: r['external'] != 0, trace), @@ -379,7 +374,6 @@ def process_trace(filename): out.write('') throughput('TOTAL', trace) throughput('MS', marksweeps) - throughput('MC', markcompacts) throughput('OLDSPACE', globalgcs) out.write('
') for chart in charts: