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.
Review URL: http://codereview.chromium.org/9020006
git-svn-id: http://v8.googlecode.com/svn/trunk@10288 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 1ac152d..643d0eb 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1779,11 +1779,12 @@
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/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 628c3d1..703666c 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -1242,6 +1242,8 @@
DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
+
+ LOperand* value() { return inputs_[0]; }
};
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index cdc464c..4b68438 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2262,27 +2262,26 @@
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<Object>(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/src/assembler.cc b/src/assembler.cc
index b66f448..2de7b92 100644
--- a/src/assembler.cc
+++ b/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/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 7883481..ab38502 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2124,26 +2124,20 @@
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<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell());
-
- int offset = JSGlobalPropertyCell::kValueOffset;
- __ mov(object, Immediate(cell_handle));
+ Register value = ToRegister(instr->value());
+ Handle<JSGlobalPropertyCell> 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/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index f364439..c503785 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1856,9 +1856,7 @@
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/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 7e126ff..cc3762d 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -1269,16 +1269,16 @@
};
-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/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 98fd57d..701450b 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -400,13 +400,19 @@
// 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/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index eaef6ff..895b4c9 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -2141,26 +2141,26 @@
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<Object>(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/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index f963ec9..1040b28 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1782,11 +1782,12 @@
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/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index efc5e27..da59dd8 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -1242,6 +1242,8 @@
DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
+
+ LOperand* value() { return inputs_[0]; }
};
diff --git a/src/runtime.cc b/src/runtime.cc
index b0e1a05..544b210 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -4326,12 +4326,26 @@
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/src/scanner.cc b/src/scanner.cc
old mode 100644
new mode 100755
diff --git a/src/type-info.cc b/src/type-info.cc
index af8a8ae..790d77c 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -85,7 +85,8 @@
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 @@
Handle<Code> code = Handle<Code>::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<Code> code = Handle<Code>::cast(map_or_code);
Map* first_map = code->FindFirstMap();
ASSERT(first_map != NULL);
- return Handle<Map>(first_map);
+ return CanRetainOtherContext(first_map, *global_context_)
+ ? Handle<Map>::null()
+ : Handle<Map>(first_map);
}
return Handle<Map>::cast(map_or_code);
}
@@ -155,7 +160,11 @@
Handle<Object> map_or_code = GetInfo(expr->id());
if (map_or_code->IsCode()) {
Handle<Code> code = Handle<Code>::cast(map_or_code);
- return Handle<Map>(code->FindFirstMap());
+ Map* first_map = code->FindFirstMap();
+ ASSERT(first_map != NULL);
+ return CanRetainOtherContext(first_map, *global_context_)
+ ? Handle<Map>::null()
+ : Handle<Map>(first_map);
}
return Handle<Map>::cast(map_or_code);
}
@@ -288,7 +297,11 @@
if (state != CompareIC::KNOWN_OBJECTS) {
return Handle<Map>::null();
}
- return Handle<Map>(code->FindFirstMap());
+ Map* first_map = code->FindFirstMap();
+ ASSERT(first_map != NULL);
+ return CanRetainOtherContext(first_map, *global_context_)
+ ? Handle<Map>::null()
+ : Handle<Map>(first_map);
}
@@ -451,20 +464,23 @@
// 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 @@
RelocInfo* info = it.rinfo();
Object* object = info->target_object();
if (object->IsMap()) {
- AddMapIfMissing(Handle<Map>(Map::cast(object)), types);
+ Map* map = Map::cast(object);
+ if (!CanRetainOtherContext(map, *global_context_)) {
+ AddMapIfMissing(Handle<Map>(map), types);
+ }
}
}
}
diff --git a/src/version.cc b/src/version.cc
index 79ea5e8..bbd26a4 100644
--- a/src/version.cc
+++ b/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/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index a96d140..70f5874 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -2028,25 +2028,27 @@
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<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell());
-
- __ movq(address, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
+ Register value = ToRegister(instr->value());
+ Handle<JSGlobalPropertyCell> 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/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 7fa8a39..ac4d5f5 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1768,11 +1768,12 @@
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/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 280d235..c6fcfeb 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1231,16 +1231,17 @@
};
-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]; }
};