Commit f42636b2 authored by bak@chromium.org's avatar bak@chromium.org

- Added fast case for extending the JSObject properties storage.

- Changed date to compute local_time_offset at load time.
  
Review URL: http://codereview.chromium.org/6441

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@420 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 28ab46c5
......@@ -561,6 +561,10 @@ static void Generate_StoreIC_Miss(MacroAssembler* masm) {
}
static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
StoreIC::GenerateExtendStorage(masm);
}
static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
StoreIC::GenerateMegamorphic(masm);
}
......
......@@ -62,6 +62,8 @@ namespace v8 { namespace internal {
V(StoreIC_Miss, BUILTIN, UNINITIALIZED) \
V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED) \
\
V(StoreIC_ExtendStorage, BUILTIN, UNINITIALIZED) \
\
V(LoadIC_Initialize, LOAD_IC, UNINITIALIZED) \
V(LoadIC_PreMonomorphic, LOAD_IC, PREMONOMORPHIC) \
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC) \
......
......@@ -36,7 +36,6 @@
// changes to these properties.
const $Date = global.Date;
// ECMA 262 - 15.9.1.2
function Day(time) {
return $floor(time/msPerDay);
......@@ -127,17 +126,6 @@ function EquivalentTime(t) {
return TimeClip(MakeDate(day, TimeWithinDay(t)));
}
var local_time_offset;
function LocalTimeOffset() {
if (IS_UNDEFINED(local_time_offset)) {
local_time_offset = %DateLocalTimeOffset();
}
return local_time_offset;
}
var daylight_cache_time = $NaN;
var daylight_cache_offset;
......@@ -170,16 +158,17 @@ function WeekDay(time) {
return Modulo(Day(time) + 4, 7);
}
var local_time_offset = %DateLocalTimeOffset();
function LocalTime(time) {
if ($isNaN(time)) return time;
return time + LocalTimeOffset() + DaylightSavingsOffset(time);
return time + local_time_offset + DaylightSavingsOffset(time);
}
function UTC(time) {
if ($isNaN(time)) return time;
var tmp = time - LocalTimeOffset();
var tmp = time - local_time_offset;
return tmp - DaylightSavingsOffset(tmp);
}
......@@ -530,7 +519,7 @@ function TimeString(time) {
function LocalTimezoneString(time) {
var timezoneOffset = (LocalTimeOffset() + DaylightSavingsOffset(time)) / msPerMinute;
var timezoneOffset = (local_time_offset + DaylightSavingsOffset(time)) / msPerMinute;
var sign = (timezoneOffset >= 0) ? 1 : -1;
var hours = $floor((sign * timezoneOffset)/60);
var min = $floor((sign * timezoneOffset)%60);
......
......@@ -86,21 +86,26 @@ void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) {
}
void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
int estimate) {
static int ExpectedNofPropertiesFromEstimate(int estimate) {
// TODO(1231235): We need dynamic feedback to estimate the number
// of expected properties in an object. The static hack below
// is barely a solution.
shared->set_expected_nof_properties(estimate + 2);
if (estimate == 0) return 4;
return estimate + 2;
}
void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
int estimate) {
shared->set_expected_nof_properties(
ExpectedNofPropertiesFromEstimate(estimate));
}
void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
int estimate) {
// TODO(1231235): We need dynamic feedback to estimate the number
// of expected properties in an object. The static hack below
// is barely a solution.
SetExpectedNofProperties(func, estimate + 2);
SetExpectedNofProperties(
func, ExpectedNofPropertiesFromEstimate(estimate));
}
......
......@@ -539,9 +539,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
}
// Defined in ic.cc.
Object* StoreIC_Miss(Arguments args);
void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : value
......@@ -560,6 +557,22 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
}
void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
// -----------------------------------
__ ldr(r3, MemOperand(sp)); // copy receiver
__ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
// Perform tail call to the entry.
__ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ExtendStorage)), 3);
}
void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
// ----------- S t a t e -------------
// -- r0 : value
......
......@@ -669,9 +669,6 @@ void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
}
// Defined in ic.cc.
Object* StoreIC_Miss(Arguments args);
void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : value
......@@ -690,6 +687,25 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
}
void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : transition map
// -- esp[0] : return address
// -- esp[4] : receiver
// -----------------------------------
// Move the return address below the arguments.
__ pop(ebx);
__ push(Operand(esp, 0));
__ push(ecx);
__ push(eax);
__ push(ebx);
// Perform tail call to the entry.
__ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ExtendStorage)), 3);
}
void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
// ----------- S t a t e -------------
// -- eax : value
......
......@@ -874,10 +874,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
}
case MAP_TRANSITION: {
if (lookup->GetAttributes() != NONE) return;
if (receiver->map()->unused_property_fields() == 0) return;
HandleScope scope;
ASSERT(type == MAP_TRANSITION &&
(receiver->map()->unused_property_fields() > 0));
ASSERT(type == MAP_TRANSITION);
Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name);
code = StubCache::ComputeStoreField(*name, *receiver, index, *transition);
......@@ -906,7 +904,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(Code::cast(code));
} else if (state == MONOMORPHIC) {
set_target(megamorphic_stub());
// Only move to mega morphic if the target changes.
if (target() != Code::cast(code)) set_target(megamorphic_stub());
}
#ifdef DEBUG
......@@ -996,10 +995,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
}
case MAP_TRANSITION: {
if (lookup->GetAttributes() == NONE) {
if (receiver->map()->unused_property_fields() == 0) return;
HandleScope scope;
ASSERT(type == MAP_TRANSITION &&
(receiver->map()->unused_property_fields() > 0));
ASSERT(type == MAP_TRANSITION);
Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name);
code = StubCache::ComputeKeyedStoreField(*name, *receiver,
......@@ -1115,6 +1112,40 @@ Object* StoreIC_Miss(Arguments args) {
}
// Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a
// JSObject.
Object* StoreIC_ExtendStorage(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 3);
// Convert the parameters
JSObject* object = JSObject::cast(args[0]);
Map* transition = Map::cast(args[1]);
Object* value = args[2];
// Check the object has run out out property space.
ASSERT(object->HasFastProperties());
ASSERT(object->map()->unused_property_fields() == 0);
// Expand the properties array.
FixedArray* old_storage = object->properties();
int new_unused = transition->unused_property_fields();
int new_size = old_storage->length() + new_unused + 1;
Object* result = old_storage->CopySize(new_size);
if (result->IsFailure()) return result;
FixedArray* new_storage = FixedArray::cast(result);
new_storage->set(old_storage->length(), value);
// Set the new property value and do the map tranistion.
object->set_properties(new_storage);
object->set_map(transition);
// Return the stored value.
return value;
}
void StoreIC::GenerateInitialize(MacroAssembler* masm) {
Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
}
......
......@@ -39,6 +39,7 @@ namespace v8 { namespace internal {
ICU(KeyedLoadIC_Miss) \
ICU(CallIC_Miss) \
ICU(StoreIC_Miss) \
ICU(StoreIC_ExtendStorage) \
ICU(KeyedStoreIC_Miss) \
/* Utilities for IC stubs. */ \
ICU(LoadCallbackProperty) \
......@@ -294,6 +295,7 @@ class StoreIC: public IC {
static void GenerateInitialize(MacroAssembler* masm);
static void GenerateMiss(MacroAssembler* masm);
static void GenerateMegamorphic(MacroAssembler* masm);
static void GenerateExtendStorage(MacroAssembler* masm);
private:
static void Generate(MacroAssembler* masm, const ExternalReference& f);
......
......@@ -416,10 +416,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
// Perform map transition for the receiver if necessary.
if (transition != NULL) {
// Update the map of the object; no write barrier updating is
// needed because the map is never in new space.
__ mov(ip, Operand(Handle<Map>(transition)));
__ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
if (object->map()->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the propeties array.
__ mov(r2, Operand(Handle<Map>(transition)));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
__ Jump(ic, RelocInfo::CODE_TARGET);
} else {
// Update the map of the object; no write barrier updating is
// needed because the map is never in new space.
__ mov(ip, Operand(Handle<Map>(transition)));
__ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
}
}
// Write to the properties array.
......
......@@ -436,10 +436,18 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Perform map transition for the receiver if necessary.
if (transition != NULL) {
// Update the map of the object; no write barrier updating is
// needed because the map is never in new space.
__ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
Immediate(Handle<Map>(transition)));
if (object->map()->unused_property_fields() == 0) {
// The properties must be extended before we can store the value.
// We jump to a runtime call that extends the propeties array.
__ mov(Operand(ecx), Immediate(Handle<Map>(transition)));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
__ jmp(ic, RelocInfo::CODE_TARGET);
} else {
// Update the map of the object; no write barrier updating is
// needed because the map is never in new space.
__ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
Immediate(Handle<Map>(transition)));
}
}
// Write to the properties array.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment