[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75
mrowe at apple.com
mrowe at apple.com
Thu Oct 29 20:46:39 UTC 2009
The following commit has been merged in the webkit-1.1 branch:
commit b190d91908ae4641b1acff65ec00253147b42001
Author: mrowe at apple.com <mrowe at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Sat Oct 17 02:31:42 2009 +0000
Roll out r49717 as it broke the build.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49726 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 6d439be..8c94bb6 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,15 +1,3 @@
-2009-10-16 Geoffrey Garen <ggaren at apple.com>
-
- Build fix: apparently we shouldn't export those symbols?
-
- * JavaScriptCore.exp:
-
-2009-10-16 Geoffrey Garen <ggaren at apple.com>
-
- Build fix: export some symbols.
-
- * JavaScriptCore.exp:
-
2009-10-16 Oliver Hunt <oliver at apple.com>
Reviewed by Gavin Barraclough.
@@ -79,122 +67,6 @@
* runtime/StringObjectThatMasqueradesAsUndefined.h:
(JSC::StringObjectThatMasqueradesAsUndefined::createStructure):
-2009-10-16 Geoffrey Garen <ggaren at apple.com>
-
- Reviewed by Oliver Hunt.
-
- Fast for-in enumeration: Cache JSPropertyNameIterator; cache JSStrings
- in JSPropertyNameIterator; inline more code.
-
- 1.024x as fast on SunSpider (fasta: 1.43x as fast).
-
- * bytecode/CodeBlock.cpp:
- (JSC::CodeBlock::dump):
- * bytecode/Opcode.h:
- * bytecompiler/BytecodeGenerator.cpp:
- (JSC::BytecodeGenerator::emitGetPropertyNames):
- (JSC::BytecodeGenerator::emitNextPropertyName):
- * bytecompiler/BytecodeGenerator.h: Added a few extra operands to
- op_get_pnames and op_next_pname so that we can track iteration state
- in the register file instead of in the JSPropertyNameIterator. (To be
- cacheable, the JSPropertyNameIterator must be stateless.)
-
- * interpreter/Interpreter.cpp:
- (JSC::Interpreter::tryCachePutByID):
- (JSC::Interpreter::tryCacheGetByID): Updated for rename to
- "normalizePrototypeChain" and removal of "isCacheable".
-
- (JSC::Interpreter::privateExecute): Updated for in-RegisterFile
- iteration state tracking.
-
- * jit/JIT.cpp:
- (JSC::JIT::privateCompileMainPass):
- * jit/JIT.h:
- * jit/JITOpcodes.cpp:
- (JSC::JIT::emit_op_get_pnames): Updated for in-RegisterFile
- iteration state tracking.
-
- (JSC::JIT::emit_op_next_pname): Inlined code generation for op_next_pname.
-
- * jit/JITStubs.cpp:
- (JSC::JITThunks::tryCachePutByID):
- (JSC::JITThunks::tryCacheGetByID): Updated for rename to
- "normalizePrototypeChain" and removal of "isCacheable".
-
- (JSC::DEFINE_STUB_FUNCTION):
- * jit/JITStubs.h:
- (JSC::): Added has_property and to_object stubs. Removed op_next_pname
- stub, since has_property is all we need anymore.
-
- * parser/Nodes.cpp:
- (JSC::ForInNode::emitBytecode): Updated for in-RegisterFile
- iteration state tracking.
-
- * runtime/JSCell.h:
- * runtime/JSObject.cpp:
- (JSC::JSObject::getPropertyNames): Don't do caching at this layer
- anymore, since we don't create a JSPropertyNameIterator at this layer.
-
- * runtime/JSPropertyNameIterator.cpp:
- (JSC::JSPropertyNameIterator::create): Do do caching at this layer.
- (JSC::JSPropertyNameIterator::get): Updated for in-RegisterFile
- iteration state tracking.
- (JSC::JSPropertyNameIterator::markChildren): Mark our JSStrings.
-
- * runtime/JSPropertyNameIterator.h:
- (JSC::JSPropertyNameIterator::size):
- (JSC::JSPropertyNameIterator::setCachedStructure):
- (JSC::JSPropertyNameIterator::cachedStructure):
- (JSC::JSPropertyNameIterator::setCachedPrototypeChain):
- (JSC::JSPropertyNameIterator::cachedPrototypeChain):
- (JSC::JSPropertyNameIterator::JSPropertyNameIterator):
- (JSC::Structure::setEnumerationCache): Don't store iteration state in
- a JSPropertyNameIterator. Do cache a JSPropertyNameIterator in a
- Structure.
-
- * runtime/JSValue.h:
- (JSC::asCell):
- * runtime/MarkStack.h: Make those mischievous #include gods happy.
-
- * runtime/ObjectConstructor.cpp:
-
- * runtime/Operations.h:
- (JSC::normalizePrototypeChain): Renamed countPrototypeChainEntriesAndCheckForProxies
- to normalizePrototypeChain, since it changes dictionary prototypes to
- non-dictionary objects.
-
- * runtime/PropertyNameArray.cpp:
- (JSC::PropertyNameArray::add):
- * runtime/PropertyNameArray.h:
- (JSC::PropertyNameArrayData::PropertyNameArrayData):
- (JSC::PropertyNameArray::data):
- (JSC::PropertyNameArray::size):
- (JSC::PropertyNameArray::begin):
- (JSC::PropertyNameArray::end): Simplified some code here to help with
- current and future refactoring.
-
- * runtime/Protect.h:
- * runtime/Structure.cpp:
- (JSC::Structure::~Structure):
- (JSC::Structure::addPropertyWithoutTransition):
- (JSC::Structure::removePropertyWithoutTransition): No need to clear
- the enumeration cache with adding / removing properties without
- transition. It is an error to add / remove properties without transition
- once an object has been observed, and we can ASSERT to catch that.
-
- * runtime/Structure.h:
- (JSC::Structure::enumerationCache): Changed the enumeration cache to
- hold a JSPropertyNameIterator.
-
- * runtime/StructureChain.cpp:
- * runtime/StructureChain.h:
- (JSC::StructureChain::head): Removed StructureChain::isCacheable because
- it was wrong-headed in two ways: (1) It gave up when a prototype was a
- dictionary, but instead we want un-dictionary heavily accessed
- prototypes; (2) It folded a test for hasDefaultGetPropertyNames() into
- a generic test for "cacheable-ness", but hasDefaultGetPropertyNames()
- is only releavant to for-in caching.
-
2009-10-16 Steve Falkenburg <sfalken at apple.com>
Reviewed by Adam Roben.
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 18ca2ae..ef0054b 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1015,18 +1015,16 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_get_pnames: {
- int r0 = it[0].u.operand;
- int r1 = it[1].u.operand;
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
- it += OPCODE_LENGTH(op_get_pnames) - 1;
break;
}
case op_next_pname: {
- int dest = it[0].u.operand;
- int iter = it[4].u.operand;
- int offset = it[5].u.operand;
+ int dest = (++it)->u.operand;
+ int iter = (++it)->u.operand;
+ int offset = (++it)->u.operand;
printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, location + offset);
- it += OPCODE_LENGTH(op_next_pname) - 1;
break;
}
case op_push_scope: {
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 8968252..c9196ce 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -152,8 +152,8 @@ namespace JSC {
macro(op_strcat, 4) \
macro(op_to_primitive, 3) \
\
- macro(op_get_pnames, 6) \
- macro(op_next_pname, 7) \
+ macro(op_get_pnames, 3) \
+ macro(op_next_pname, 4) \
\
macro(op_push_scope, 2) \
macro(op_pop_scope, 1) \
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 41b5c39..780a52e 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -1794,28 +1794,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetSco
return target;
}
-RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
-{
- size_t begin = instructions().size();
-
- emitOpcode(op_get_pnames);
- instructions().append(dst->index());
- instructions().append(base->index());
- instructions().append(i->index());
- instructions().append(size->index());
- instructions().append(breakTarget->bind(begin, instructions().size()));
- return dst;
-}
-
-RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
+RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target)
{
size_t begin = instructions().size();
emitOpcode(op_next_pname);
instructions().append(dst->index());
- instructions().append(base->index());
- instructions().append(i->index());
- instructions().append(size->index());
instructions().append(iter->index());
instructions().append(target->bind(begin, instructions().size()));
return dst;
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 61de173..1a83ce9 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -312,8 +312,8 @@ namespace JSC {
PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
void emitSubroutineReturn(RegisterID* retAddrSrc);
- RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
- RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
+ RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base); }
+ RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target);
RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 53964ad..74b4eb1 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -938,20 +938,22 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock*
return;
}
+ StructureChain* protoChain = structure->prototypeChain(callFrame);
+ if (!protoChain->isCacheable()) {
+ vPC[0] = getOpcode(op_put_by_id_generic);
+ return;
+ }
+
// Structure transition, cache transition info
if (slot.type() == PutPropertySlot::NewProperty) {
if (structure->isDictionary()) {
vPC[0] = getOpcode(op_put_by_id_generic);
return;
}
-
- // put_by_id_transition checks the prototype chain for setters.
- normalizePrototypeChain(callFrame, baseCell);
-
vPC[0] = getOpcode(op_put_by_id_transition);
vPC[4] = structure->previousID();
vPC[5] = structure;
- vPC[6] = structure->prototypeChain(callFrame);
+ vPC[6] = protoChain;
vPC[7] = slot.cachedOffset();
codeBlock->refStructures(vPC);
return;
@@ -1047,15 +1049,21 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
return;
}
- size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase());
+ size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
if (!count) {
vPC[0] = getOpcode(op_get_by_id_generic);
return;
}
+ StructureChain* protoChain = structure->prototypeChain(callFrame);
+ if (!protoChain->isCacheable()) {
+ vPC[0] = getOpcode(op_get_by_id_generic);
+ return;
+ }
+
vPC[0] = getOpcode(op_get_by_id_chain);
vPC[4] = structure;
- vPC[5] = structure->prototypeChain(callFrame);
+ vPC[5] = protoChain;
vPC[6] = count;
vPC[7] = slot.cachedOffset();
codeBlock->refStructures(vPC);
@@ -3494,63 +3502,41 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_get_pnames) {
- /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset)
+ /* get_pnames dst(r) base(r)
Creates a property name list for register base and puts it
- in register dst, initializing i and size for iteration. If
- base is undefined or null, jumps to breakTarget.
+ in register dst. This is not a true JavaScript value, just
+ a synthetic value used to keep the iteration state in a
+ register.
*/
int dst = vPC[1].u.operand;
int base = vPC[2].u.operand;
- int i = vPC[3].u.operand;
- int size = vPC[4].u.operand;
- int breakTarget = vPC[5].u.operand;
- JSValue v = callFrame->r(base).jsValue();
- if (v.isUndefinedOrNull()) {
- vPC += breakTarget;
- NEXT_INSTRUCTION();
- }
-
- JSObject* o = v.toObject(callFrame);
- Structure* structure = o->structure();
- JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
- if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
- jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
-
- callFrame->r(dst) = jsPropertyNameIterator;
- callFrame->r(base) = JSValue(o);
- callFrame->r(i) = Register::withInt(0);
- callFrame->r(size) = Register::withInt(jsPropertyNameIterator->size());
+ callFrame->r(dst) = JSPropertyNameIterator::create(callFrame, callFrame->r(base).jsValue());
vPC += OPCODE_LENGTH(op_get_pnames);
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_next_pname) {
- /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset)
+ /* next_pname dst(r) iter(r) target(offset)
- Copies the next name from the property name list in
- register iter to dst, then jumps to offset target. If there are no
- names left, invalidates the iterator and continues to the next
+ Tries to copies the next name from property name list in
+ register iter. If there are names left, then copies one to
+ register dst, and jumps to offset target. If there are none
+ left, invalidates the iterator and continues to the next
instruction.
*/
int dst = vPC[1].u.operand;
- int base = vPC[2].u.operand;
- int i = vPC[3].u.operand;
- int size = vPC[4].u.operand;
- int iter = vPC[5].u.operand;
- int target = vPC[6].u.operand;
+ int iter = vPC[2].u.operand;
+ int target = vPC[3].u.operand;
JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
- while (callFrame->r(i).i() != callFrame->r(size).i()) {
- JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
- callFrame->r(i) = Register::withInt(callFrame->r(i).i() + 1);
- if (key) {
- CHECK_FOR_TIMEOUT();
- callFrame->r(dst) = key;
- vPC += target;
- NEXT_INSTRUCTION();
- }
+ if (JSValue temp = it->next(callFrame)) {
+ CHECK_FOR_TIMEOUT();
+ callFrame->r(dst) = JSValue(temp);
+ vPC += target;
+ NEXT_INSTRUCTION();
}
+ it->invalidate();
vPC += OPCODE_LENGTH(op_next_pname);
NEXT_INSTRUCTION();
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index fa0ac2e..5cead1d 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -202,6 +202,7 @@ void JIT::privateCompileMainPass()
DEFINE_BINARY_OP(op_less)
DEFINE_BINARY_OP(op_lesseq)
DEFINE_BINARY_OP(op_urshift)
+ DEFINE_UNARY_OP(op_get_pnames)
DEFINE_UNARY_OP(op_is_boolean)
DEFINE_UNARY_OP(op_is_function)
DEFINE_UNARY_OP(op_is_number)
@@ -240,7 +241,6 @@ void JIT::privateCompileMainPass()
DEFINE_OP(op_get_by_id)
DEFINE_OP(op_get_by_val)
DEFINE_OP(op_get_global_var)
- DEFINE_OP(op_get_pnames)
DEFINE_OP(op_get_scoped_var)
DEFINE_OP(op_instanceof)
DEFINE_OP(op_jeq_null)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 23e8883..0712743 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -713,7 +713,6 @@ namespace JSC {
void emit_op_new_func_exp(Instruction*);
void emit_op_new_object(Instruction*);
void emit_op_new_regexp(Instruction*);
- void emit_op_get_pnames(Instruction*);
void emit_op_next_pname(Instruction*);
void emit_op_not(Instruction*);
void emit_op_nstricteq(Instruction*);
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index 59bc403..c793f90 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -33,7 +33,6 @@
#include "JSArray.h"
#include "JSCell.h"
#include "JSFunction.h"
-#include "JSPropertyNameIterator.h"
#include "LinkBuffer.h"
namespace JSC {
@@ -1196,109 +1195,23 @@ void JIT::emit_op_throw(Instruction* currentInstruction)
#endif
}
-void JIT::emit_op_get_pnames(Instruction* currentInstruction)
-{
- int dst = currentInstruction[1].u.operand;
- int base = currentInstruction[2].u.operand;
- int i = currentInstruction[3].u.operand;
- int size = currentInstruction[4].u.operand;
- int breakTarget = currentInstruction[5].u.operand;
-
- JumpList isNotObject;
-
- emitLoad(base, regT1, regT0);
- if (!m_codeBlock->isKnownNotImmediate(base))
- isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
- if (base != m_codeBlock->thisRegister()) {
- loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
- isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
- }
-
- // We could inline the case where you have a valid cache, but
- // this call doesn't seem to be hot.
- Label isObject(this);
- JITStubCall getPnamesStubCall(this, cti_op_get_pnames);
- getPnamesStubCall.addArgument(regT0);
- getPnamesStubCall.call(dst);
- load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
- store32(Imm32(0), addressFor(i));
- store32(regT3, addressFor(size));
- Jump end = jump();
-
- isNotObject.link(this);
- addJump(branch32(Equal, regT1, Imm32(JSValue::NullTag)), breakTarget);
- addJump(branch32(Equal, regT1, Imm32(JSValue::UndefinedTag)), breakTarget);
- JITStubCall toObjectStubCall(this, cti_to_object);
- toObjectStubCall.addArgument(regT1, regT0);
- toObjectStubCall.call(base);
- jump().linkTo(isObject, this);
-
- end.link(this);
-}
-
void JIT::emit_op_next_pname(Instruction* currentInstruction)
{
int dst = currentInstruction[1].u.operand;
- int base = currentInstruction[2].u.operand;
- int i = currentInstruction[3].u.operand;
- int size = currentInstruction[4].u.operand;
- int it = currentInstruction[5].u.operand;
- int target = currentInstruction[6].u.operand;
-
- JumpList callHasProperty;
-
- Label begin(this);
- load32(addressFor(i), regT0);
- Jump end = branch32(Equal, regT0, addressFor(size));
-
- // Grab key @ i
- loadPtr(addressFor(it), regT1);
- loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
- load32(BaseIndex(regT2, regT0, TimesEight), regT2);
- store32(Imm32(JSValue::CellTag), tagFor(dst));
- store32(regT2, payloadFor(dst));
-
- // Increment i
- add32(Imm32(1), regT0);
- store32(regT0, addressFor(i));
-
- // Verify that i is valid:
- loadPtr(addressFor(base), regT0);
+ int iter = currentInstruction[2].u.operand;
+ int target = currentInstruction[3].u.operand;
- // Test base's structure
- loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
- callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
-
- // Test base's prototype chain
- loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3);
- loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3);
- addJump(branchTestPtr(Zero, Address(regT3)), target);
-
- Label checkPrototype(this);
- callHasProperty.append(branch32(Equal, Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::NullTag)));
- loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
- loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
- callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
- addPtr(Imm32(sizeof(Structure*)), regT3);
- branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
+ load32(Address(callFrameRegister, (iter * sizeof(Register))), regT0);
- // Continue loop.
- addJump(jump(), target);
-
- // Slow case: Ask the object if i is valid.
- callHasProperty.link(this);
- loadPtr(addressFor(dst), regT1);
- JITStubCall stubCall(this, cti_has_property);
+ JITStubCall stubCall(this, cti_op_next_pname);
stubCall.addArgument(regT0);
- stubCall.addArgument(regT1);
stubCall.call();
- // Test for valid key.
- addJump(branchTest32(NonZero, regT0), target);
- jump().linkTo(begin, this);
-
- // End of loop.
- end.link(this);
+ Jump endOfIter = branchTestPtr(Zero, regT0);
+ emitStore(dst, regT1, regT0);
+ map(m_bytecodeIndex + OPCODE_LENGTH(op_next_pname), dst, regT1, regT0);
+ addJump(jump(), target);
+ endOfIter.link(this);
}
void JIT::emit_op_push_scope(Instruction* currentInstruction)
@@ -2459,110 +2372,15 @@ void JIT::emit_op_throw(Instruction* currentInstruction)
#endif
}
-void JIT::emit_op_get_pnames(Instruction* currentInstruction)
-{
- int dst = currentInstruction[1].u.operand;
- int base = currentInstruction[2].u.operand;
- int i = currentInstruction[3].u.operand;
- int size = currentInstruction[4].u.operand;
- int breakTarget = currentInstruction[5].u.operand;
-
- JumpList isNotObject;
-
- emitGetVirtualRegister(base, regT0);
- if (!m_codeBlock->isKnownNotImmediate(base))
- isNotObject.append(emitJumpIfNotJSCell(regT0));
- if (base != m_codeBlock->thisRegister()) {
- loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
- isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
- }
-
- // We could inline the case where you have a valid cache, but
- // this call doesn't seem to be hot.
- Label isObject(this);
- JITStubCall getPnamesStubCall(this, cti_op_get_pnames);
- getPnamesStubCall.addArgument(regT0);
- getPnamesStubCall.call(dst);
- load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
- store32(Imm32(0), addressFor(i));
- store32(regT3, addressFor(size));
- Jump end = jump();
-
- isNotObject.link(this);
- move(regT0, regT1);
- and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT1);
- addJump(branch32(Equal, regT1, Imm32(JSImmediate::FullTagTypeNull)), breakTarget);
-
- JITStubCall toObjectStubCall(this, cti_to_object);
- toObjectStubCall.addArgument(regT0);
- toObjectStubCall.call(base);
- jump().linkTo(isObject, this);
-
- end.link(this);
-}
-
void JIT::emit_op_next_pname(Instruction* currentInstruction)
{
- int dst = currentInstruction[1].u.operand;
- int base = currentInstruction[2].u.operand;
- int i = currentInstruction[3].u.operand;
- int size = currentInstruction[4].u.operand;
- int it = currentInstruction[5].u.operand;
- int target = currentInstruction[6].u.operand;
-
- JumpList callHasProperty;
-
- Label begin(this);
- load32(addressFor(i), regT0);
- Jump end = branch32(Equal, regT0, addressFor(size));
-
- // Grab key @ i
- loadPtr(addressFor(it), regT1);
- loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
- loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2);
- emitPutVirtualRegister(dst, regT2);
-
- // Increment i
- add32(Imm32(1), regT0);
- store32(regT0, addressFor(i));
-
- // Verify that i is valid:
- emitGetVirtualRegister(base, regT0);
-
- // Test base's structure
- loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
- callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
-
- // Test base's prototype chain
- loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3);
- loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3);
- addJump(branchTestPtr(Zero, Address(regT3)), target);
-
- Label checkPrototype(this);
- loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
- callHasProperty.append(emitJumpIfNotJSCell(regT2));
- loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
- callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
- addPtr(Imm32(sizeof(Structure*)), regT3);
- branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
-
- // Continue loop.
- addJump(jump(), target);
-
- // Slow case: Ask the object if i is valid.
- callHasProperty.link(this);
- emitGetVirtualRegister(dst, regT1);
- JITStubCall stubCall(this, cti_has_property);
- stubCall.addArgument(regT0);
- stubCall.addArgument(regT1);
+ JITStubCall stubCall(this, cti_op_next_pname);
+ stubCall.addArgument(currentInstruction[2].u.operand, regT2);
stubCall.call();
-
- // Test for valid key.
- addJump(branchTest32(NonZero, regT0), target);
- jump().linkTo(begin, this);
-
- // End of loop.
- end.link(this);
+ Jump endOfIter = branchTestPtr(Zero, regT0);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
+ addJump(jump(), currentInstruction[3].u.operand);
+ endOfIter.link(this);
}
void JIT::emit_op_push_scope(Instruction* currentInstruction)
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 90ea807..ccdde37 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -700,15 +700,11 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
// Structure transition, cache transition info
if (slot.type() == PutPropertySlot::NewProperty) {
- if (structure->isDictionary()) {
+ StructureChain* prototypeChain = structure->prototypeChain(callFrame);
+ if (!prototypeChain->isCacheable() || structure->isDictionary()) {
ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
return;
}
-
- // put_by_id_transition checks the prototype chain for setters.
- normalizePrototypeChain(callFrame, baseCell);
-
- StructureChain* prototypeChain = structure->prototypeChain(callFrame);
stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
return;
@@ -784,13 +780,17 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
return;
}
- size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase());
+ size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
if (!count) {
stubInfo->accessType = access_get_by_id_generic;
return;
}
StructureChain* prototypeChain = structure->prototypeChain(callFrame);
+ if (!prototypeChain->isCacheable()) {
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
+ return;
+ }
stubInfo->initGetByIdChain(structure, prototypeChain);
JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, slot.cachedOffset(), returnAddress);
}
@@ -1332,11 +1332,15 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
- } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase())) {
+ } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) {
+ StructureChain* protoChain = structure->prototypeChain(callFrame);
+ if (!protoChain->isCacheable()) {
+ ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+ return JSValue::encode(result);
+ }
+
int listIndex;
PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
-
- StructureChain* protoChain = structure->prototypeChain(callFrame);
JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, slot.cachedOffset());
if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
@@ -2667,22 +2671,18 @@ DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
{
STUB_INIT_STACK_FRAME(stackFrame);
- CallFrame* callFrame = stackFrame.callFrame;
- JSObject* o = stackFrame.args[0].jsObject();
- Structure* structure = o->structure();
- JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
- if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
- jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
- return jsPropertyNameIterator;
+ return JSPropertyNameIterator::create(stackFrame.callFrame, stackFrame.args[0].jsValue());
}
-DEFINE_STUB_FUNCTION(int, has_property)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_next_pname)
{
STUB_INIT_STACK_FRAME(stackFrame);
- JSObject* base = stackFrame.args[0].jsObject();
- JSString* property = stackFrame.args[1].jsString();
- return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value()));
+ JSPropertyNameIterator* it = stackFrame.args[0].propertyNameIterator();
+ JSValue temp = it->next(stackFrame.callFrame);
+ if (!temp)
+ it->invalidate();
+ return JSValue::encode(temp);
}
DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
@@ -3023,14 +3023,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw)
return JSValue::encode(exceptionValue);
}
-DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
-}
-
} // namespace JSC
#endif // ENABLE(JIT)
diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h
index ccbcd2a..daae043 100644
--- a/JavaScriptCore/jit/JITStubs.h
+++ b/JavaScriptCore/jit/JITStubs.h
@@ -63,7 +63,6 @@ namespace JSC {
int32_t asInt32;
JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
- JSObject* jsObject() { return static_cast<JSObject*>(asPointer); }
Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
int32_t int32() { return asInt32; }
CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
@@ -286,6 +285,7 @@ extern "C" {
EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION);
+ EncodedJSValue JIT_STUB cti_op_next_pname(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION);
@@ -307,7 +307,6 @@ extern "C" {
EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION);
JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION);
JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
@@ -333,7 +332,6 @@ extern "C" {
int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
int JIT_STUB cti_op_loop_if_true(STUB_ARGS_DECLARATION);
int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
- int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp
index b1e317e..3bd318a 100644
--- a/JavaScriptCore/parser/Nodes.cpp
+++ b/JavaScriptCore/parser/Nodes.cpp
@@ -1468,16 +1468,14 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
if (!m_lexpr->isLocation())
return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
+ RefPtr<Label> continueTarget = generator.newLabel();
+
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
if (m_init)
generator.emitNode(generator.ignoredResult(), m_init);
-
- RefPtr<RegisterID> base = generator.newTemporary();
- generator.emitNode(base.get(), m_expr);
- RefPtr<RegisterID> i = generator.newTemporary();
- RefPtr<RegisterID> size = generator.newTemporary();
- RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
+ RegisterID* forInBase = generator.emitNode(m_expr);
+ RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
generator.emitJump(scope->continueTarget());
RefPtr<Label> loopStart = generator.newLabel();
@@ -1519,7 +1517,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
generator.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
- generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
+ generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
generator.emitLabel(scope->breakTarget());
return dst;
diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h
index 16a5131..63c58ac 100644
--- a/JavaScriptCore/runtime/JSCell.h
+++ b/JavaScriptCore/runtime/JSCell.h
@@ -112,6 +112,14 @@ namespace JSC {
Structure* m_structure;
};
+ // FIXME: We should deprecate this and just use JSValue::asCell() instead.
+ JSCell* asCell(JSValue);
+
+ inline JSCell* asCell(JSValue value)
+ {
+ return value.asCell();
+ }
+
inline JSCell::JSCell(Structure* structure)
: m_structure(structure)
{
diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp
index 6932ded..b24af32 100644
--- a/JavaScriptCore/runtime/JSObject.cpp
+++ b/JavaScriptCore/runtime/JSObject.cpp
@@ -443,22 +443,45 @@ bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyNa
void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
- getOwnPropertyNames(exec, propertyNames);
+ bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_structure->isDictionary());
- if (prototype().isNull())
- return;
+ if (shouldCache) {
+ if (PropertyNameArrayData* data = m_structure->enumerationCache()) {
+ if (data->cachedPrototypeChain() == m_structure->prototypeChain(exec)) {
+ propertyNames.setData(data);
+ return;
+ }
- JSObject* prototype = asObject(this->prototype());
- while(1) {
- if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
- prototype->getPropertyNames(exec, propertyNames);
- break;
+ m_structure->clearEnumerationCache();
}
- prototype->getOwnPropertyNames(exec, propertyNames);
- JSValue nextProto = prototype->prototype();
- if (nextProto.isNull())
- break;
- prototype = asObject(nextProto);
+ }
+
+ getOwnPropertyNames(exec, propertyNames);
+
+ if (prototype().isObject()) {
+ propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
+ JSObject* prototype = asObject(this->prototype());
+ while(1) {
+ if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
+ prototype->getPropertyNames(exec, propertyNames);
+ break;
+ }
+ prototype->getOwnPropertyNames(exec, propertyNames);
+ JSValue nextProto = prototype->prototype();
+ if (!nextProto.isObject())
+ break;
+ prototype = asObject(nextProto);
+ }
+ }
+
+ if (shouldCache) {
+ StructureChain* protoChain = m_structure->prototypeChain(exec);
+ if (!protoChain->isCacheable())
+ return;
+ RefPtr<PropertyNameArrayData> data = propertyNames.data();
+ data->setCachedPrototypeChain(protoChain);
+ data->setCachedStructure(m_structure);
+ m_structure->setEnumerationCache(data.release());
}
}
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index 2cd9f75..e08a3d9 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -29,56 +29,26 @@
#include "config.h"
#include "JSPropertyNameIterator.h"
-#include "JSGlobalObject.h"
-
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
-JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
+JSPropertyNameIterator::~JSPropertyNameIterator()
{
- ASSERT(!o->structure()->enumerationCache() ||
- o->structure()->enumerationCache()->cachedStructure() != o->structure() ||
- o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
-
- PropertyNameArray propertyNames(exec);
- o->getPropertyNames(exec, propertyNames);
- JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data());
-
- if (o->structure()->isDictionary())
- return jsPropertyNameIterator;
-
- if (o->structure()->typeInfo().overridesGetPropertyNames())
- return jsPropertyNameIterator;
-
- size_t count = normalizePrototypeChain(exec, o);
- StructureChain* structureChain = o->structure()->prototypeChain(exec);
- RefPtr<Structure>* structure = structureChain->head();
- for (size_t i = 0; i < count; ++i) {
- if (structure[i]->typeInfo().overridesGetPropertyNames())
- return jsPropertyNameIterator;
- }
-
- jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
- jsPropertyNameIterator->setCachedStructure(o->structure());
- o->structure()->setEnumerationCache(jsPropertyNameIterator);
- return jsPropertyNameIterator;
}
-JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
+void JSPropertyNameIterator::markChildren(MarkStack& markStack)
{
- JSValue& identifier = m_jsStrings[i];
- if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
- return identifier;
-
- if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value())))
- return JSValue();
- return identifier;
+ JSCell::markChildren(markStack);
+ if (m_object)
+ markStack.append(m_object);
}
-void JSPropertyNameIterator::markChildren(MarkStack& markStack)
+void JSPropertyNameIterator::invalidate()
{
- markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
+ ASSERT(m_position == m_end);
+ m_object = 0;
+ m_data.clear();
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h
index 0559e0b..2b66d2b 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -31,7 +31,6 @@
#include "JSObject.h"
#include "JSString.h"
-#include "Operations.h"
#include "PropertyNameArray.h"
namespace JSC {
@@ -40,51 +39,73 @@ namespace JSC {
class JSObject;
class JSPropertyNameIterator : public JSCell {
- friend class JIT;
-
public:
- static JSPropertyNameIterator* create(ExecState*, JSObject*);
+ static JSPropertyNameIterator* create(ExecState*, JSValue);
+
+ virtual ~JSPropertyNameIterator();
+
+ virtual void markChildren(MarkStack&);
+
+ JSValue next(ExecState*);
+ void invalidate();
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren));
}
-
- virtual void markChildren(MarkStack&);
-
- JSValue get(ExecState*, JSObject*, size_t i);
- size_t size() { return m_jsStringsSize; }
-
- void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
- Structure* cachedStructure() { return m_cachedStructure; }
-
- void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
- StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
-
private:
- JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData);
+ JSPropertyNameIterator(ExecState*);
+ JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
- Structure* m_cachedStructure;
- RefPtr<StructureChain> m_cachedPrototypeChain;
- size_t m_jsStringsSize;
- OwnArrayPtr<JSValue> m_jsStrings;
+ JSObject* m_object;
+ RefPtr<PropertyNameArrayData> m_data;
+ PropertyNameArrayData::const_iterator m_position;
+ PropertyNameArrayData::const_iterator m_end;
};
-inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData)
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec)
: JSCell(exec->globalData().propertyNameIteratorStructure.get())
- , m_cachedStructure(0)
- , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
- , m_jsStrings(new JSValue[m_jsStringsSize])
+ , m_object(0)
+ , m_position(0)
+ , m_end(0)
{
- PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
- for (size_t i = 0; i < m_jsStringsSize; ++i)
- m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
}
-inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
+ : JSCell(exec->globalData().propertyNameIteratorStructure.get())
+ , m_object(object)
+ , m_data(propertyNameArrayData)
+ , m_position(m_data->begin())
+ , m_end(m_data->end())
+{
+}
+
+inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v)
{
- ASSERT(!isDictionary());
- m_enumerationCache = enumerationCache;
+ if (v.isUndefinedOrNull())
+ return new (exec) JSPropertyNameIterator(exec);
+
+ JSObject* o = v.toObject(exec);
+ PropertyNameArray propertyNames(exec);
+ o->getPropertyNames(exec, propertyNames);
+ return new (exec) JSPropertyNameIterator(exec, o, propertyNames.releaseData());
+}
+
+inline JSValue JSPropertyNameIterator::next(ExecState* exec)
+{
+ if (m_position == m_end)
+ return JSValue();
+
+ if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec))
+ return jsOwnedString(exec, (*m_position++).ustring());
+
+ do {
+ if (m_object->hasProperty(exec, *m_position))
+ return jsOwnedString(exec, (*m_position++).ustring());
+ m_position++;
+ } while (m_position != m_end);
+
+ return JSValue();
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h
index 1063cdc..3c511d8 100644
--- a/JavaScriptCore/runtime/JSValue.h
+++ b/JavaScriptCore/runtime/JSValue.h
@@ -373,14 +373,6 @@ namespace JSC {
return static_cast<uint32_t>(val);
}
- // FIXME: We should deprecate this and just use JSValue::asCell() instead.
- JSCell* asCell(JSValue);
-
- inline JSCell* asCell(JSValue value)
- {
- return value.asCell();
- }
-
ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
{
if (isInt32())
diff --git a/JavaScriptCore/runtime/MarkStack.h b/JavaScriptCore/runtime/MarkStack.h
index ea09f54..ba00057 100644
--- a/JavaScriptCore/runtime/MarkStack.h
+++ b/JavaScriptCore/runtime/MarkStack.h
@@ -47,7 +47,7 @@ namespace JSC {
}
ALWAYS_INLINE void append(JSValue);
- void append(JSCell*);
+ ALWAYS_INLINE void append(JSCell*);
ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues)
{
diff --git a/JavaScriptCore/runtime/ObjectConstructor.cpp b/JavaScriptCore/runtime/ObjectConstructor.cpp
index 837d5a6..a456423 100644
--- a/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -125,7 +125,6 @@ JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec,
return description;
}
-// FIXME: Use the enumeration cache.
JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args)
{
if (!args.at(0).isObject())
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
index 1aa68b3..5da9e38 100644
--- a/JavaScriptCore/runtime/Operations.h
+++ b/JavaScriptCore/runtime/Operations.h
@@ -224,15 +224,15 @@ namespace JSC {
return jsAddSlowCase(callFrame, v1, v2);
}
- inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase)
+ inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue baseValue, const PropertySlot& slot)
{
- JSCell* cell = asCell(base);
+ JSCell* cell = asCell(baseValue);
size_t count = 0;
- while (slotBase != cell) {
+ while (slot.slotBase() != cell) {
JSValue v = cell->structure()->prototypeForLookup(callFrame);
- // If we didn't find slotBase in base's prototype chain, then base
+ // If we didn't find slotBase in baseValue's prototype chain, then baseValue
// must be a proxy for another object.
if (v.isNull())
@@ -252,25 +252,6 @@ namespace JSC {
return count;
}
- inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
- {
- size_t count = 0;
- while (1) {
- JSValue v = base->structure()->prototypeForLookup(callFrame);
- if (v.isNull())
- return count;
-
- base = asCell(v);
-
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (base->structure()->isDictionary())
- asObject(base)->setStructure(Structure::fromDictionaryTransition(base->structure()));
-
- ++count;
- }
- }
-
ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
{
ScopeChainIterator iter = scopeChain->begin();
diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp
index c28b6a4..cff2605 100644
--- a/JavaScriptCore/runtime/PropertyNameArray.cpp
+++ b/JavaScriptCore/runtime/PropertyNameArray.cpp
@@ -47,7 +47,7 @@ void PropertyNameArray::add(UString::Rep* identifier)
return;
}
- addKnownUnique(identifier);
+ m_data->propertyNameVector().append(Identifier(m_globalData, identifier));
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/PropertyNameArray.h b/JavaScriptCore/runtime/PropertyNameArray.h
index 3dbcc9d..7d6edd0 100644
--- a/JavaScriptCore/runtime/PropertyNameArray.h
+++ b/JavaScriptCore/runtime/PropertyNameArray.h
@@ -24,7 +24,6 @@
#include "CallFrame.h"
#include "Identifier.h"
#include <wtf/HashSet.h>
-#include <wtf/OwnArrayPtr.h>
#include <wtf/Vector.h>
namespace JSC {
@@ -32,26 +31,39 @@ namespace JSC {
class Structure;
class StructureChain;
- // FIXME: Rename to PropertyNameArray.
class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
public:
typedef Vector<Identifier, 20> PropertyNameVector;
+ typedef PropertyNameVector::const_iterator const_iterator;
static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
+ const_iterator begin() const { return m_propertyNameVector.begin(); }
+ const_iterator end() const { return m_propertyNameVector.end(); }
+
PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
+ void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
+ Structure* cachedStructure() const { return m_cachedStructure; }
+
+ void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+
private:
PropertyNameArrayData()
+ : m_cachedStructure(0)
{
}
PropertyNameVector m_propertyNameVector;
+ Structure* m_cachedStructure;
+ RefPtr<StructureChain> m_cachedPrototypeChain;
};
- // FIXME: Rename to PropertyNameArrayBuilder.
class PropertyNameArray {
public:
+ typedef PropertyNameArrayData::const_iterator const_iterator;
+
PropertyNameArray(JSGlobalData* globalData)
: m_data(PropertyNameArrayData::create())
, m_globalData(globalData)
@@ -72,18 +84,21 @@ namespace JSC {
void add(UString::Rep*);
void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
+ size_t size() const { return m_data->propertyNameVector().size(); }
+
Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
+ const_iterator begin() const { return m_data->begin(); }
+ const_iterator end() const { return m_data->end(); }
+
void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
PropertyNameArrayData* data() { return m_data.get(); }
+
PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
- // FIXME: Remove these functions.
- typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
- size_t size() const { return m_data->propertyNameVector().size(); }
- const_iterator begin() const { return m_data->propertyNameVector().begin(); }
- const_iterator end() const { return m_data->propertyNameVector().end(); }
+ void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; }
+ bool shouldCache() const { return m_shouldCache; }
private:
typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
diff --git a/JavaScriptCore/runtime/Protect.h b/JavaScriptCore/runtime/Protect.h
index a0d5443..224164d 100644
--- a/JavaScriptCore/runtime/Protect.h
+++ b/JavaScriptCore/runtime/Protect.h
@@ -22,8 +22,8 @@
#ifndef Protect_h
#define Protect_h
+#include "JSCell.h"
#include "Collector.h"
-#include "JSValue.h"
namespace JSC {
diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp
index a11050f..643a49a 100644
--- a/JavaScriptCore/runtime/Structure.cpp
+++ b/JavaScriptCore/runtime/Structure.cpp
@@ -28,10 +28,9 @@
#include "Identifier.h"
#include "JSObject.h"
-#include "JSPropertyNameIterator.h"
-#include "Lookup.h"
#include "PropertyNameArray.h"
#include "StructureChain.h"
+#include "Lookup.h"
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/RefPtr.h>
@@ -160,9 +159,9 @@ Structure::~Structure()
m_previous->table.removeAnonymousSlotTransition(m_anonymousSlotsInPrevious);
}
-
- if (m_enumerationCache)
- m_enumerationCache->setCachedStructure(0);
+
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructure(0);
if (m_propertyTable) {
unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
@@ -283,6 +282,13 @@ void Structure::materializePropertyMap()
}
}
+void Structure::clearEnumerationCache()
+{
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructure(0);
+ m_cachedPropertyNameArrayData.clear();
+}
+
void Structure::growPropertyStorageCapacity()
{
if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
@@ -546,25 +552,25 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
- ASSERT(!m_enumerationCache);
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
size_t offset = put(propertyName, attributes, specificValue);
if (propertyStorageSize() > propertyStorageCapacity())
growPropertyStorageCapacity();
+ clearEnumerationCache();
return offset;
}
size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
{
ASSERT(isUncacheableDictionary());
- ASSERT(!m_enumerationCache);
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
size_t offset = remove(propertyName);
+ clearEnumerationCache();
return offset;
}
diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h
index 2496c1b..a027b1a 100644
--- a/JavaScriptCore/runtime/Structure.h
+++ b/JavaScriptCore/runtime/Structure.h
@@ -31,7 +31,6 @@
#include "JSValue.h"
#include "PropertyMapHashTable.h"
#include "PropertyNameArray.h"
-#include "Protect.h"
#include "StructureChain.h"
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
@@ -124,8 +123,9 @@ namespace JSC {
JSCell* specificValue() { return m_specificValueInPrevious; }
void despecifyDictionaryFunction(const Identifier& propertyName);
- void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
- JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); }
+ void setEnumerationCache(PassRefPtr<PropertyNameArrayData> data) { m_cachedPropertyNameArrayData = data; }
+ PropertyNameArrayData* enumerationCache() { return m_cachedPropertyNameArrayData.get(); }
+ void clearEnumerationCache();
void getEnumerablePropertyNames(PropertyNameArray&);
private:
@@ -186,7 +186,7 @@ namespace JSC {
StructureTransitionTable table;
- ProtectedPtr<JSPropertyNameIterator> m_enumerationCache;
+ RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
PropertyMapHashTable* m_propertyTable;
diff --git a/JavaScriptCore/runtime/StructureChain.cpp b/JavaScriptCore/runtime/StructureChain.cpp
index 085876c..0a9bc69 100644
--- a/JavaScriptCore/runtime/StructureChain.cpp
+++ b/JavaScriptCore/runtime/StructureChain.cpp
@@ -46,4 +46,18 @@ StructureChain::StructureChain(Structure* head)
m_vector[i] = 0;
}
+bool StructureChain::isCacheable() const
+{
+ uint32_t i = 0;
+
+ while (m_vector[i]) {
+ // Both classes of dictionary structure may change arbitrarily so we can't cache them
+ if (m_vector[i]->isDictionary())
+ return false;
+ if (m_vector[i++]->typeInfo().overridesGetPropertyNames())
+ return false;
+ }
+ return true;
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/StructureChain.h b/JavaScriptCore/runtime/StructureChain.h
index 816b66d..c48749d 100644
--- a/JavaScriptCore/runtime/StructureChain.h
+++ b/JavaScriptCore/runtime/StructureChain.h
@@ -36,11 +36,10 @@ namespace JSC {
class Structure;
class StructureChain : public RefCounted<StructureChain> {
- friend class JIT;
-
public:
static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
RefPtr<Structure>* head() { return m_vector.get(); }
+ bool isCacheable() const;
private:
StructureChain(Structure* head);
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 27622d5..b3430bb 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -34,12 +34,6 @@
(WebCore::getExceptionCodeDescription):
* dom/ExceptionCode.h:
-2009-10-16 Geoffrey Garen <ggaren at apple.com>
-
- Build fix: forgot to check in this #include.
-
- * bridge/runtime_root.h:
-
2009-10-16 Simon Fraser <simon.fraser at apple.com>
Reviewed by Dan Bernstein.
diff --git a/WebCore/bridge/runtime_root.h b/WebCore/bridge/runtime_root.h
index 1806bf5..eacbb57 100644
--- a/WebCore/bridge/runtime_root.h
+++ b/WebCore/bridge/runtime_root.h
@@ -31,7 +31,6 @@
#endif
#include <runtime/Protect.h>
-#include <wtf/Forward.h>
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/RefCounted.h>
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list