Revision: 8751
Author: [email protected]
Date: Thu Jul 28 02:15:17 2011
Log: Version 3.5.1.
Fixed setting the readonly flag on the prototype property using the API
call FunctionTemplate::SetPrototypeAttributes (issue 1539).
Changed the tools/test.py script to use d8 instead of shell for testing.
Fixed crash in ToBooleanStub when GC happens during invocation.
Enabled automatic unboxing of double arrays.
Performance improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=8751
Modified:
/trunk
/trunk/ChangeLog
/trunk/include/v8.h
/trunk/src/api.cc
/trunk/src/apinatives.js
/trunk/src/code-stubs.h
/trunk/src/d8.cc
/trunk/src/date.js
/trunk/src/debug-debugger.js
/trunk/src/flag-definitions.h
/trunk/src/heap-inl.h
/trunk/src/heap.cc
/trunk/src/heap.h
/trunk/src/hydrogen-instructions.cc
/trunk/src/hydrogen-instructions.h
/trunk/src/hydrogen.cc
/trunk/src/hydrogen.h
/trunk/src/ia32/code-stubs-ia32.cc
/trunk/src/ia32/full-codegen-ia32.cc
/trunk/src/ia32/lithium-codegen-ia32.cc
/trunk/src/json-parser.h
/trunk/src/json.js
/trunk/src/macros.py
/trunk/src/mirror-debugger.js
/trunk/src/objects-inl.h
/trunk/src/objects.cc
/trunk/src/objects.h
/trunk/src/regexp-macro-assembler-irregexp-inl.h
/trunk/src/regexp.js
/trunk/src/runtime.cc
/trunk/src/runtime.h
/trunk/src/type-info.cc
/trunk/src/type-info.h
/trunk/src/version.cc
/trunk/src/x64/lithium-codegen-x64.cc
/trunk/test/benchmarks/testcfg.py
/trunk/test/cctest/test-api.cc
/trunk/test/es5conform/testcfg.py
/trunk/test/message/testcfg.py
/trunk/test/mjsunit/array-constructor.js
/trunk/test/mjsunit/array-functions-prototype-misc.js
/trunk/test/mjsunit/global-load-from-eval-in-with.js
/trunk/test/mjsunit/local-load-from-eval.js
/trunk/test/mjsunit/property-load-across-eval.js
/trunk/test/mjsunit/regress/regress-269.js
/trunk/test/mjsunit/regress/regress-334.js
/trunk/test/mjsunit/testcfg.py
/trunk/test/mozilla/testcfg.py
/trunk/test/sputnik/testcfg.py
/trunk/test/test262/testcfg.py
/trunk/tools/oom_dump/README
/trunk/tools/test.py
=======================================
--- /trunk/ChangeLog Mon Jul 25 04:05:35 2011
+++ /trunk/ChangeLog Thu Jul 28 02:15:17 2011
@@ -1,3 +1,18 @@
+2011-07-28: Version 3.5.1
+
+ Fixed setting the readonly flag on the prototype property using the
+ API call FunctionTemplate::SetPrototypeAttributes (issue 1539).
+
+ Changed the tools/test.py script to use d8 instead of shell for
+ testing.
+
+ Fixed crash in ToBooleanStub when GC happens during invocation.
+
+ Enabled automatic unboxing of double arrays.
+
+ Performance improvements on all platforms.
+
+
2011-07-25: Version 3.5.0
Implemented Object.prototype.{hasOwnProperty,
propertyIsEnumerable} for
=======================================
--- /trunk/include/v8.h Wed Jul 20 06:44:42 2011
+++ /trunk/include/v8.h Thu Jul 28 02:15:17 2011
@@ -2231,11 +2231,10 @@
void SetHiddenPrototype(bool value);
/**
- * Sets the property attributes of the 'prototype' property of functions
- * created from this FunctionTemplate. Can be any combination of
ReadOnly,
- * DontEnum and DontDelete.
+ * Sets the ReadOnly flag in the attributes of the 'prototype' property
+ * of functions created from this FunctionTemplate to true.
*/
- void SetPrototypeAttributes(int attributes);
+ void ReadOnlyPrototype();
/**
* Returns true if the given object is an instance of this function
=======================================
--- /trunk/src/api.cc Wed Jul 20 06:44:42 2011
+++ /trunk/src/api.cc Thu Jul 28 02:15:17 2011
@@ -877,7 +877,6 @@
i::Handle<i::FunctionTemplateInfo> info) {
info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
info->set_flag(0);
- info->set_prototype_attributes(i::Smi::FromInt(v8::None));
}
@@ -1100,14 +1099,13 @@
}
-void FunctionTemplate::SetPrototypeAttributes(int attributes) {
+void FunctionTemplate::ReadOnlyPrototype() {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if
(IsDeadCheck(isolate, "v8::FunctionTemplate::SetPrototypeAttributes()")) {
return;
}
ENTER_V8(isolate);
- Utils::OpenHandle(this)->set_prototype_attributes(
- i::Smi::FromInt(attributes));
+ Utils::OpenHandle(this)->set_read_only_prototype(true);
}
=======================================
--- /trunk/src/apinatives.js Mon Jun 27 06:21:41 2011
+++ /trunk/src/apinatives.js Thu Jul 28 02:15:17 2011
@@ -73,14 +73,10 @@
if (name) %FunctionSetName(fun, name);
cache[serialNumber] = fun;
var prototype = %GetTemplateField(data, kApiPrototypeTemplateOffset);
- var attributes = %GetTemplateField(data,
kApiPrototypeAttributesOffset);
- if (attributes != NONE) {
- %IgnoreAttributesAndSetProperty(
- fun, "prototype",
- prototype ? Instantiate(prototype) : {},
- attributes);
- } else {
- fun.prototype = prototype ? Instantiate(prototype) : {};
+ var flags = %GetTemplateField(data, kApiFlagOffset);
+ fun.prototype = prototype ? Instantiate(prototype) : {};
+ if (flags & (1 << kReadOnlyPrototypeBit)) {
+ %FunctionSetReadOnlyPrototype(fun);
}
%SetProperty(fun.prototype, "constructor", fun, DONT_ENUM);
var parent = %GetTemplateField(data, kApiParentTemplateOffset);
=======================================
--- /trunk/src/code-stubs.h Mon Jul 25 04:05:35 2011
+++ /trunk/src/code-stubs.h Thu Jul 28 02:15:17 2011
@@ -922,6 +922,7 @@
explicit Types(byte bits) : set_(bits) {}
bool IsEmpty() const { return set_.IsEmpty(); }
+ bool IsAll() const { return ToByte() == ((1 << NUMBER_OF_TYPES) - 1); }
bool Contains(Type type) const { return set_.Contains(type); }
void Add(Type type) { set_.Add(type); }
byte ToByte() const { return set_.ToIntegral(); }
@@ -932,6 +933,9 @@
private:
EnumSet<Type, byte> set_;
};
+
+ static Types no_types() { return Types(); }
+ static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
explicit ToBooleanStub(Register tos, Types types = Types())
: tos_(tos), types_(types) { }
=======================================
--- /trunk/src/d8.cc Wed Jul 20 06:44:42 2011
+++ /trunk/src/d8.cc Thu Jul 28 02:15:17 2011
@@ -199,7 +199,7 @@
printf(" ");
}
v8::String::Utf8Value str(args[i]);
- int n = fwrite(*str, sizeof(**str), str.length(), stdout);
+ int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(),
stdout));
if (n != str.length()) {
printf("Error in fwrite\n");
exit(1);
@@ -231,7 +231,7 @@
do { // Repeat if the line ends with an escape '\'.
// fgets got an error. Just give up.
if (fgets(buffer, kBufferSize, stdin) == NULL) return Null();
- length = strlen(buffer);
+ length = static_cast<int>(strlen(buffer));
linebreak = (length > 1 && buffer[length-2] == '\\');
if (linebreak) buffer[length-2] = '\n';
accumulator = String::Concat(accumulator, String::New(buffer,
length-1));
@@ -299,9 +299,12 @@
Persistent<Object> persistent_array = Persistent<Object>::New(array);
persistent_array.MakeWeak(data, ExternalArrayWeakCallback);
persistent_array.MarkIndependent();
- array->SetIndexedPropertiesToExternalArrayData(data, type, length);
- array->Set(String::New("length"), Int32::New(length), ReadOnly);
- array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size));
+ array->SetIndexedPropertiesToExternalArrayData(data, type,
+ static_cast<int>(length));
+ array->Set(String::New("length"),
+ Int32::New(static_cast<int32_t>(length)), ReadOnly);
+ array->Set(String::New("BYTES_PER_ELEMENT"),
+ Int32::New(static_cast<int32_t>(element_size)));
return array;
}
@@ -790,7 +793,7 @@
char* chars = new char[size + 1];
chars[size] = '\0';
for (int i = 0; i < size;) {
- int read = fread(&chars[i], 1, size - i, file);
+ int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
i += read;
}
fclose(file);
@@ -981,7 +984,7 @@
char* chars = new char[size + 1];
chars[size] = '\0';
for (int i = 0; i < size;) {
- int read = fread(&chars[i], 1, size - i, file);
+ int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
i += read;
}
fclose(file);
=======================================
--- /trunk/src/flag-definitions.h Wed Jul 13 06:23:34 2011
+++ /trunk/src/flag-definitions.h Thu Jul 28 02:15:17 2011
@@ -100,7 +100,7 @@
DEFINE_bool(harmony_proxies, false, "enable harmony proxies")
// Flags for experimental implementation features.
-DEFINE_bool(unbox_double_arrays, false, "automatically unbox arrays of
doubles")
+DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of
doubles")
// Flags for Crankshaft.
#ifdef V8_TARGET_ARCH_MIPS
=======================================
--- /trunk/src/heap-inl.h Mon Jul 25 04:05:35 2011
+++ /trunk/src/heap-inl.h Thu Jul 28 02:15:17 2011
@@ -140,6 +140,11 @@
MaybeObject* Heap::CopyFixedArray(FixedArray* src) {
return CopyFixedArrayWithMap(src, src->map());
}
+
+
+MaybeObject* Heap::CopyFixedDoubleArray(FixedDoubleArray* src) {
+ return CopyFixedDoubleArrayWithMap(src, src->map());
+}
MaybeObject* Heap::AllocateRaw(int size_in_bytes,
=======================================
--- /trunk/src/heap.cc Wed Jul 20 06:44:42 2011
+++ /trunk/src/heap.cc Thu Jul 28 02:15:17 2011
@@ -3388,17 +3388,22 @@
object_size);
}
- FixedArray* elements = FixedArray::cast(source->elements());
+ FixedArrayBase* elements = FixedArrayBase::cast(source->elements());
FixedArray* properties = FixedArray::cast(source->properties());
// Update elements if necessary.
if (elements->length() > 0) {
Object* elem;
- { MaybeObject* maybe_elem =
- (elements->map() == fixed_cow_array_map()) ?
- elements : CopyFixedArray(elements);
+ { MaybeObject* maybe_elem;
+ if (elements->map() == fixed_cow_array_map()) {
+ maybe_elem = FixedArray::cast(elements);
+ } else if (source->HasFastDoubleElements()) {
+ maybe_elem =
CopyFixedDoubleArray(FixedDoubleArray::cast(elements));
+ } else {
+ maybe_elem = CopyFixedArray(FixedArray::cast(elements));
+ }
if (!maybe_elem->ToObject(&elem)) return maybe_elem;
}
- JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
+ JSObject::cast(clone)->set_elements(FixedArrayBase::cast(elem));
}
// Update properties if necessary.
if (properties->length() > 0) {
@@ -3755,6 +3760,23 @@
for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
return result;
}
+
+
+MaybeObject* Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src,
+ Map* map) {
+ int len = src->length();
+ Object* obj;
+ { MaybeObject* maybe_obj = AllocateRawFixedDoubleArray(len, NOT_TENURED);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
+ HeapObject* dst = HeapObject::cast(obj);
+ dst->set_map(map);
+ CopyBlock(
+ dst->address() + FixedDoubleArray::kLengthOffset,
+ src->address() + FixedDoubleArray::kLengthOffset,
+ FixedDoubleArray::SizeFor(len) - FixedDoubleArray::kLengthOffset);
+ return obj;
+}
MaybeObject* Heap::AllocateFixedArray(int length) {
=======================================
--- /trunk/src/heap.h Wed Jul 20 06:44:42 2011
+++ /trunk/src/heap.h Thu Jul 28 02:15:17 2011
@@ -617,6 +617,16 @@
// Failure::RetryAfterGC(requested_bytes, space) if the allocation
failed.
MUST_USE_RESULT MaybeObject* CopyFixedArrayWithMap(FixedArray* src, Map*
map);
+ // Make a copy of src and return it. Returns
+ // Failure::RetryAfterGC(requested_bytes, space) if the allocation
failed.
+ MUST_USE_RESULT inline MaybeObject* CopyFixedDoubleArray(
+ FixedDoubleArray* src);
+
+ // Make a copy of src, set the map, and return the copy. Returns
+ // Failure::RetryAfterGC(requested_bytes, space) if the allocation
failed.
+ MUST_USE_RESULT MaybeObject* CopyFixedDoubleArrayWithMap(
+ FixedDoubleArray* src, Map* map);
+
// Allocates a fixed array initialized with the hole values.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the
allocation
// failed.
=======================================
--- /trunk/src/hydrogen-instructions.cc Mon Jul 25 04:05:35 2011
+++ /trunk/src/hydrogen-instructions.cc Thu Jul 28 02:15:17 2011
@@ -1228,6 +1228,30 @@
}
return HValue::InferRange();
}
+
+
+Range* HShr::InferRange() {
+ if (right()->IsConstant()) {
+ HConstant* c = HConstant::cast(right());
+ if (c->HasInteger32Value()) {
+ int shift_count = c->Integer32Value() & 0x1f;
+ if (left()->range()->CanBeNegative()) {
+ // Only compute bounds if the result always fits into an int32.
+ return (shift_count >= 1)
+ ? new Range(0, static_cast<uint32_t>(0xffffffff) >>
shift_count)
+ : new Range();
+ } else {
+ // For positive inputs we can use the >> operator.
+ Range* result = (left()->range() != NULL)
+ ? left()->range()->Copy()
+ : new Range();
+ result->Sar(c->Integer32Value());
+ return result;
+ }
+ }
+ }
+ return HValue::InferRange();
+}
Range* HShl::InferRange() {
=======================================
--- /trunk/src/hydrogen-instructions.h Mon Jul 25 04:05:35 2011
+++ /trunk/src/hydrogen-instructions.h Thu Jul 28 02:15:17 2011
@@ -184,6 +184,7 @@
V(InobjectFields) \
V(BackingStoreFields) \
V(ArrayElements) \
+ V(DoubleArrayElements) \
V(SpecializedArrayElements) \
V(GlobalVars) \
V(Maps) \
@@ -933,8 +934,12 @@
class HBranch: public HUnaryControlInstruction {
public:
- HBranch(HValue* value, HBasicBlock* true_target, HBasicBlock*
false_target)
- : HUnaryControlInstruction(value, true_target, false_target) {
+ HBranch(HValue* value,
+ HBasicBlock* true_target,
+ HBasicBlock* false_target,
+ ToBooleanStub::Types expected_input_types =
ToBooleanStub::no_types())
+ : HUnaryControlInstruction(value, true_target, false_target),
+ expected_input_types_(expected_input_types) {
ASSERT(true_target != NULL && false_target != NULL);
}
explicit HBranch(HValue* value)
@@ -944,8 +949,15 @@
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::None();
}
+
+ ToBooleanStub::Types expected_input_types() const {
+ return expected_input_types_;
+ }
DECLARE_CONCRETE_INSTRUCTION(Branch)
+
+ private:
+ ToBooleanStub::Types expected_input_types_;
};
@@ -3060,6 +3072,7 @@
HShr(HValue* context, HValue* left, HValue* right)
: HBitwiseBinaryOperation(context, left, right) { }
+ virtual Range* InferRange();
virtual HType CalculateInferredType();
DECLARE_CONCRETE_INSTRUCTION(Shr)
@@ -3524,7 +3537,7 @@
SetOperandAt(0, elements);
SetOperandAt(1, key);
set_representation(Representation::Double());
- SetFlag(kDependsOnArrayElements);
+ SetFlag(kDependsOnDoubleArrayElements);
SetFlag(kUseGVN);
}
@@ -3742,7 +3755,7 @@
SetOperandAt(0, elements);
SetOperandAt(1, key);
SetOperandAt(2, val);
- SetFlag(kChangesArrayElements);
+ SetFlag(kChangesDoubleArrayElements);
}
virtual Representation RequiredInputRepresentation(int index) const {
=======================================
--- /trunk/src/hydrogen.cc Mon Jul 25 04:05:35 2011
+++ /trunk/src/hydrogen.cc Thu Jul 28 02:15:17 2011
@@ -736,6 +736,8 @@
HPhase phase("Assign dominators", this);
for (int i = 0; i < blocks_.length(); ++i) {
if (blocks_[i]->IsLoopHeader()) {
+ // Only the first predecessor of a loop header is from outside the
loop.
+ // All others are back edges, and thus cannot dominate the loop
header.
blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first());
} else {
for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) {
@@ -743,13 +745,15 @@
}
}
}
-
- // Propagate flag marking blocks containing unconditional deoptimize.
+}
+
+// Mark all blocks that are dominated by an unconditional soft deoptimize
to
+// prevent code motion across those blocks.
+void HGraph::PropagateDeoptimizingMark() {
+ HPhase phase("Propagate deoptimizing mark", this);
MarkAsDeoptimizingRecursively(entry_block());
}
-
-// Mark all blocks that are dominated by an unconditional deoptimize.
void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
HBasicBlock* dominated = block->dominated_blocks()->at(i);
@@ -2158,7 +2162,9 @@
}
HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
- HBranch* test = new(zone()) HBranch(value, empty_true, empty_false);
+ unsigned test_id = condition()->test_id();
+ ToBooleanStub::Types
expected(builder->oracle()->ToBooleanTypes(test_id));
+ HBranch* test = new(zone()) HBranch(value, empty_true, empty_false,
expected);
builder->current_block()->Finish(test);
empty_true->Goto(if_true());
@@ -2293,6 +2299,7 @@
graph()->OrderBlocks();
graph()->AssignDominators();
+ graph()->PropagateDeoptimizingMark();
graph()->EliminateRedundantPhis();
if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
if (!graph()->CollectPhis()) {
@@ -5504,9 +5511,11 @@
// We need an extra block to maintain edge-split form.
HBasicBlock* empty_block = graph()->CreateBasicBlock();
HBasicBlock* eval_right = graph()->CreateBasicBlock();
+ unsigned test_id = expr->left()->test_id();
+ ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id));
HBranch* test = is_logical_and
- ? new(zone()) HBranch(Top(), eval_right, empty_block)
- : new(zone()) HBranch(Top(), empty_block, eval_right);
+ ? new(zone()) HBranch(Top(), eval_right, empty_block, expected)
+ : new(zone()) HBranch(Top(), empty_block, eval_right, expected);
current_block()->Finish(test);
set_current_block(eval_right);
=======================================
--- /trunk/src/hydrogen.h Wed Jul 6 04:27:02 2011
+++ /trunk/src/hydrogen.h Thu Jul 28 02:15:17 2011
@@ -238,7 +238,7 @@
void OrderBlocks();
void AssignDominators();
void ReplaceCheckedValues();
- void MarkAsDeoptimizingRecursively(HBasicBlock* block);
+ void PropagateDeoptimizingMark();
// Returns false if there are phi-uses of the arguments-object
// which are not supported by the optimizing compiler.
@@ -293,6 +293,7 @@
HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
Object* value);
+ void MarkAsDeoptimizingRecursively(HBasicBlock* block);
void InsertTypeConversions(HInstruction* instr);
void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi);
@@ -718,6 +719,8 @@
HBasicBlock* CreateJoin(HBasicBlock* first,
HBasicBlock* second,
int join_id);
+
+ TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
private:
// Type of a member function that generates inline code for a native
function.
@@ -747,7 +750,6 @@
CompilationInfo* info() const {
return function_state()->compilation_info();
}
- TypeFeedbackOracle* oracle() const { return function_state()->oracle(); }
AstContext* call_context() const {
return function_state()->call_context();
=======================================
--- /trunk/src/ia32/code-stubs-ia32.cc Mon Jul 25 04:05:35 2011
+++ /trunk/src/ia32/code-stubs-ia32.cc Thu Jul 28 02:15:17 2011
@@ -348,8 +348,10 @@
__ ret(1 * kPointerSize);
}
- __ bind(&patch);
- GenerateTypeTransition(masm);
+ if (!types_.IsAll()) {
+ __ bind(&patch);
+ GenerateTypeTransition(masm);
+ }
}
=======================================
--- /trunk/src/ia32/full-codegen-ia32.cc Wed Jul 13 06:23:34 2011
+++ /trunk/src/ia32/full-codegen-ia32.cc Thu Jul 28 02:15:17 2011
@@ -572,7 +572,7 @@
Label* fall_through) {
ToBooleanStub stub(result_register());
__ push(result_register());
- __ CallStub(&stub);
+ __ CallStub(&stub, condition->test_id());
__ test(result_register(), Operand(result_register()));
// The stub returns nonzero for true.
Split(not_zero, if_true, if_false, fall_through);
=======================================
--- /trunk/src/ia32/lithium-codegen-ia32.cc Wed Jul 20 06:44:42 2011
+++ /trunk/src/ia32/lithium-codegen-ia32.cc Thu Jul 28 02:15:17 2011
@@ -1424,7 +1424,7 @@
// The conversion stub doesn't cause garbage collections so it's
// safe to not record a safepoint after the call.
__ bind(&call_stub);
- ToBooleanStub stub(eax);
+ ToBooleanStub stub(eax, ToBooleanStub::all_types());
__ pushad();
__ push(reg);
__ CallStub(&stub);
@@ -2232,7 +2232,6 @@
void LCodeGen::DoLoadKeyedFastDoubleElement(
LLoadKeyedFastDoubleElement* instr) {
- Register elements = ToRegister(instr->elements());
XMMRegister result = ToDoubleRegister(instr->result());
if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3097,7 +3096,6 @@
void LCodeGen::DoStoreKeyedFastDoubleElement(
LStoreKeyedFastDoubleElement* instr) {
XMMRegister value = ToDoubleRegister(instr->value());
- Register elements = ToRegister(instr->elements());
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) :
no_reg;
Label have_value;
=======================================
--- /trunk/src/json-parser.h Wed Jul 6 04:27:02 2011
+++ /trunk/src/json-parser.h Thu Jul 28 02:15:17 2011
@@ -166,7 +166,8 @@
template <bool seq_ascii>
Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
isolate_ = source->map()->isolate();
- source_ = Handle<String>(source->TryFlattenGetString());
+ FlattenString(source);
+ source_ = source;
source_length_ = source_->length();
// Optimized fast case where we only have ASCII characters.
=======================================
--- /trunk/src/macros.py Mon Jun 27 06:21:41 2011
+++ /trunk/src/macros.py Thu Jul 28 02:15:17 2011
@@ -44,7 +44,7 @@
const kApiConstructorOffset = 2;
const kApiPrototypeTemplateOffset = 5;
const kApiParentTemplateOffset = 6;
-const kApiPrototypeAttributesOffset = 15;
+const kApiFlagOffset = 14;
const NO_HINT = 0;
const NUMBER_HINT = 1;
@@ -65,6 +65,7 @@
# For apinatives.js
const kUninitialized = -1;
+const kReadOnlyPrototypeBit = 3; # For FunctionTemplateInfo, matches
objects.h
# Note: kDayZeroInJulianDay = ToJulianDay(1970, 0, 1).
const kInvalidDate = 'Invalid Date';
=======================================
--- /trunk/src/objects-inl.h Mon Jul 25 04:05:35 2011
+++ /trunk/src/objects-inl.h Thu Jul 28 02:15:17 2011
@@ -1964,6 +1964,17 @@
fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
}
+
+
+template<typename Shape, typename Key>
+int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
+ const int kMinCapacity = 32;
+ int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
+ if (capacity < kMinCapacity) {
+ capacity = kMinCapacity; // Guarantee min capacity.
+ }
+ return capacity;
+}
template<typename Shape, typename Key>
@@ -3268,8 +3279,6 @@
ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
kAccessCheckInfoOffset)
ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
-ACCESSORS(FunctionTemplateInfo, prototype_attributes, Smi,
- kPrototypeAttributesOffset)
ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
@@ -3324,6 +3333,8 @@
BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
kNeedsAccessCheckBit)
+BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
+ kReadOnlyPrototypeBit)
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
kIsExpressionBit)
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
=======================================
--- /trunk/src/objects.cc Mon Jul 25 04:05:35 2011
+++ /trunk/src/objects.cc Thu Jul 28 02:15:17 2011
@@ -2471,6 +2471,9 @@
// callback setter removed. The two lines looking up the LookupResult
// result are also added. If one of the functions is changed, the other
// should be.
+// Note that this method cannot be used to set the prototype of a function
+// because ConvertDescriptorToField() which is called in "case CALLBACKS:"
+// doesn't handle function prototypes correctly.
MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
String* name,
Object* value,
@@ -2896,9 +2899,12 @@
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
: array->length();
+ int old_capacity = 0;
+ int used_elements = 0;
+ GetElementsCapacityAndUsage(&old_capacity, &used_elements);
NumberDictionary* dictionary = NULL;
{ Object* object;
- MaybeObject* maybe = NumberDictionary::Allocate(length);
+ MaybeObject* maybe = NumberDictionary::Allocate(used_elements);
if (!maybe->ToObject(&object)) return maybe;
dictionary = NumberDictionary::cast(object);
}
@@ -8615,7 +8621,7 @@
} else {
new_length = dictionary->max_number_key() + 1;
}
- MaybeObject* result = ShouldConvertToFastDoubleElements()
+ MaybeObject* result = CanConvertToFastDoubleElements()
? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
: SetFastElementsCapacityAndLength(new_length, new_length);
if (result->IsFailure()) return result;
@@ -9157,7 +9163,15 @@
bool JSObject::HasDenseElements() {
int capacity = 0;
- int number_of_elements = 0;
+ int used = 0;
+ GetElementsCapacityAndUsage(&capacity, &used);
+ return (capacity == 0) || (used > (capacity / 2));
+}
+
+
+void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
+ *capacity = 0;
+ *used = 0;
FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
FixedArray* backing_store = NULL;
@@ -9168,34 +9182,33 @@
backing_store = FixedArray::cast(backing_store_base);
if (backing_store->IsDictionary()) {
NumberDictionary* dictionary =
NumberDictionary::cast(backing_store);
- capacity = dictionary->Capacity();
- number_of_elements = dictionary->NumberOfElements();
+ *capacity = dictionary->Capacity();
+ *used = dictionary->NumberOfElements();
break;
}
// Fall through.
case FAST_ELEMENTS:
backing_store = FixedArray::cast(backing_store_base);
- capacity = backing_store->length();
- for (int i = 0; i < capacity; ++i) {
- if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
+ *capacity = backing_store->length();
+ for (int i = 0; i < *capacity; ++i) {
+ if (!backing_store->get(i)->IsTheHole()) ++(*used);
}
break;
case DICTIONARY_ELEMENTS: {
NumberDictionary* dictionary =
NumberDictionary::cast(FixedArray::cast(elements()));
- capacity = dictionary->Capacity();
- number_of_elements = dictionary->NumberOfElements();
+ *capacity = dictionary->Capacity();
+ *used = dictionary->NumberOfElements();
break;
}
case FAST_DOUBLE_ELEMENTS: {
FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
- capacity = elms->length();
- for (int i = 0; i < capacity; i++) {
- if (!elms->is_the_hole(i)) number_of_elements++;
+ *capacity = elms->length();
+ for (int i = 0; i < *capacity; i++) {
+ if (!elms->is_the_hole(i)) ++(*used);
}
break;
}
- case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
@@ -9203,31 +9216,34 @@
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS:
- case EXTERNAL_DOUBLE_ELEMENTS: {
- return true;
- }
- }
- return (capacity == 0) || (number_of_elements > (capacity / 2));
+ case EXTERNAL_DOUBLE_ELEMENTS:
+ case EXTERNAL_PIXEL_ELEMENTS:
+ // External arrays are considered 100% used.
+ ExternalArray* external_array = ExternalArray::cast(elements());
+ *capacity = external_array->length();
+ *used = external_array->length();
+ break;
+ }
}
bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
- if (new_capacity <= kMaxFastElementsLength) return false;
- // Keep the array in fast case if the current backing storage is
- // almost filled and if the new capacity is no more than twice the
- // old capacity.
- int old_capacity = 0;
- if (elements()->map() == GetHeap()->non_strict_arguments_elements_map())
{
- FixedArray* backing_store = FixedArray::cast(elements());
- old_capacity = FixedArray::cast(backing_store->get(1))->length();
- } else if (HasFastElements()) {
- old_capacity = FixedArray::cast(elements())->length();
- } else if (HasFastDoubleElements()) {
- old_capacity = FixedDoubleArray::cast(elements())->length();
- } else {
- UNREACHABLE();
- }
- return !HasDenseElements() || ((new_capacity / 2) > old_capacity);
+ STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
+ kMaxUncheckedFastElementsLength);
+ if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
+ (new_capacity <= kMaxUncheckedFastElementsLength &&
+ GetHeap()->InNewSpace(this))) {
+ return false;
+ }
+ // If the fast-case backing storage takes up roughly three times as
+ // much space (in machine words) as a dictionary backing storage
+ // would, the object should have slow elements.
+ int old_capacity = 0;
+ int used_elements = 0;
+ GetElementsCapacityAndUsage(&old_capacity, &used_elements);
+ int dictionary_size = NumberDictionary::ComputeCapacity(used_elements) *
+ NumberDictionary::kEntrySize;
+ return 3 * dictionary_size <= new_capacity;
}
@@ -9250,20 +9266,21 @@
// dictionary, we cannot go back to fast case.
if (dictionary->requires_slow_elements()) return false;
// If the dictionary backing storage takes up roughly half as much
- // space as a fast-case backing storage would the array should have
- // fast elements.
- uint32_t length = 0;
+ // space (in machine words) as a fast-case backing storage would,
+ // the object should have fast elements.
+ uint32_t array_size = 0;
if (IsJSArray()) {
- CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
+ CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
} else {
- length = dictionary->max_number_key();
- }
- return static_cast<uint32_t>(dictionary->Capacity()) >=
- (length / (2 * NumberDictionary::kEntrySize));
+ array_size = dictionary->max_number_key();
+ }
+ uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity())
*
+ NumberDictionary::kEntrySize;
+ return 2 * dictionary_size >= array_size;
}
-bool JSObject::ShouldConvertToFastDoubleElements() {
+bool JSObject::CanConvertToFastDoubleElements() {
if (FLAG_unbox_double_arrays) {
ASSERT(HasDictionaryElements());
NumberDictionary* dictionary = NumberDictionary::cast(elements());
@@ -10194,11 +10211,8 @@
template<typename Shape, typename Key>
MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
PretenureFlag pretenure) {
- const int kMinCapacity = 32;
- int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
- if (capacity < kMinCapacity) {
- capacity = kMinCapacity; // Guarantee min capacity.
- } else if (capacity > HashTable::kMaxCapacity) {
+ int capacity = ComputeCapacity(at_least_space_for);
+ if (capacity > HashTable::kMaxCapacity) {
return Failure::OutOfMemoryException();
}
=======================================
--- /trunk/src/objects.h Mon Jul 25 04:05:35 2011
+++ /trunk/src/objects.h Thu Jul 28 02:15:17 2011
@@ -1654,7 +1654,7 @@
bool ShouldConvertToFastElements();
// Returns true if the elements of JSObject contains only values that
can be
// represented in a FixedDoubleArray.
- bool ShouldConvertToFastDoubleElements();
+ bool CanConvertToFastDoubleElements();
// Tells whether the index'th element is present.
inline bool HasElement(uint32_t index);
@@ -1948,8 +1948,21 @@
// Also maximal value of JSArray's length property.
static const uint32_t kMaxElementCount = 0xffffffffu;
+ // Constants for heuristics controlling conversion of fast elements
+ // to slow elements.
+
+ // Maximal gap that can be introduced by adding an element beyond
+ // the current elements length.
static const uint32_t kMaxGap = 1024;
- static const int kMaxFastElementsLength = 5000;
+
+ // Maximal length of fast elements array that won't be checked for
+ // being dense enough on expansion.
+ static const int kMaxUncheckedFastElementsLength = 5000;
+
+ // Same as above but for old arrays. This limit is more strict. We
+ // don't want to be wasteful with long lived objects.
+ static const int kMaxUncheckedOldFastElementsLength = 500;
+
static const int kInitialMaxFastElementArray = 100000;
static const int kMaxFastProperties = 12;
static const int kMaxInstanceSize = 255 * kPointerSize;
@@ -2015,6 +2028,9 @@
// Returns true if most of the elements backing storage is used.
bool HasDenseElements();
+ // Gets the current elements capacity and the number of used elements.
+ void GetElementsCapacityAndUsage(int* capacity, int* used);
+
bool CanSetCallback(String* name);
MUST_USE_RESULT MaybeObject* SetElementCallback(
uint32_t index,
@@ -2491,6 +2507,10 @@
int at_least_space_for,
PretenureFlag pretenure = NOT_TENURED);
+ // Computes the required capacity for a table holding the given
+ // number of elements. May be more than HashTable::kMaxCapacity.
+ static int ComputeCapacity(int at_least_space_for);
+
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
@@ -6846,7 +6866,6 @@
DECL_ACCESSORS(instance_call_handler, Object)
DECL_ACCESSORS(access_check_info, Object)
DECL_ACCESSORS(flag, Smi)
- DECL_ACCESSORS(prototype_attributes, Smi)
// Following properties use flag bits.
DECL_BOOLEAN_ACCESSORS(hidden_prototype)
@@ -6854,6 +6873,7 @@
// If the bit is set, object instances created by this function
// requires access check.
DECL_BOOLEAN_ACCESSORS(needs_access_check)
+ DECL_BOOLEAN_ACCESSORS(read_only_prototype)
static inline FunctionTemplateInfo* cast(Object* obj);
@@ -6886,14 +6906,14 @@
static const int kAccessCheckInfoOffset =
kInstanceCallHandlerOffset + kPointerSize;
static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
- static const int kPrototypeAttributesOffset = kFlagOffset + kPointerSize;
- static const int kSize = kPrototypeAttributesOffset + kPointerSize;
+ static const int kSize = kFlagOffset + kPointerSize;
private:
// Bit position in the flag, from least significant bit position.
static const int kHiddenPrototypeBit = 0;
static const int kUndetectableBit = 1;
static const int kNeedsAccessCheckBit = 2;
+ static const int kReadOnlyPrototypeBit = 3;
DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
};
=======================================
--- /trunk/src/runtime.cc Mon Jul 25 04:05:35 2011
+++ /trunk/src/runtime.cc Thu Jul 28 02:15:17 2011
@@ -219,9 +219,21 @@
}
break;
}
- default:
- UNREACHABLE();
+ case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
+ UNIMPLEMENTED();
break;
+ case JSObject::EXTERNAL_PIXEL_ELEMENTS:
+ case JSObject::EXTERNAL_BYTE_ELEMENTS:
+ case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case JSObject::EXTERNAL_SHORT_ELEMENTS:
+ case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case JSObject::EXTERNAL_INT_ELEMENTS:
+ case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case JSObject::EXTERNAL_FLOAT_ELEMENTS:
+ case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
+ case JSObject::FAST_DOUBLE_ELEMENTS:
+ // No contained objects, nothing to do.
+ break;
}
return copy;
}
@@ -1666,7 +1678,9 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
ASSERT(args.length() == 3);
CONVERT_SMI_ARG_CHECKED(elements_count, 0);
- if (elements_count > JSArray::kMaxFastElementsLength) {
+ if (elements_count < 0 ||
+ elements_count > FixedArray::kMaxLength ||
+ !Smi::IsValid(elements_count)) {
return isolate->ThrowIllegalOperation();
}
Object* new_object;
@@ -1966,6 +1980,61 @@
}
return args[0]; // return TOS
}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
+ NoHandleAllocation ha;
+ RUNTIME_ASSERT(args.length() == 1);
+ CONVERT_CHECKED(JSFunction, function, args[0]);
+
+ MaybeObject* maybe_name =
+ isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
+ String* name;
+ if (!maybe_name->To(&name)) return maybe_name;
+
+ if (function->HasFastProperties()) {
+ // Construct a new field descriptor with updated attributes.
+ DescriptorArray* instance_desc =
function->map()->instance_descriptors();
+ int index = instance_desc->Search(name);
+ ASSERT(index != DescriptorArray::kNotFound);
+ PropertyDetails details(instance_desc->GetDetails(index));
+ CallbacksDescriptor new_desc(name,
+ instance_desc->GetValue(index),
+ static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
+ details.index());
+ // Construct a new field descriptors array containing the new
descriptor.
+ Object* descriptors_unchecked;
+ { MaybeObject* maybe_descriptors_unchecked =
+ instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
+ if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
+ return maybe_descriptors_unchecked;
+ }
+ }
+ DescriptorArray* new_descriptors =
+ DescriptorArray::cast(descriptors_unchecked);
+ // Create a new map featuring the new field descriptors array.
+ Object* map_unchecked;
+ { MaybeObject* maybe_map_unchecked =
function->map()->CopyDropDescriptors();
+ if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
+ return maybe_map_unchecked;
+ }
+ }
+ Map* new_map = Map::cast(map_unchecked);
+ new_map->set_instance_descriptors(new_descriptors);
+ function->set_map(new_map);
+ } else { // Dictionary properties.
+ // Directly manipulate the property details.
+ int entry = function->property_dictionary()->FindEntry(name);
+ ASSERT(entry != StringDictionary::kNotFound);
+ PropertyDetails details =
function->property_dictionary()->DetailsAt(entry);
+ PropertyDetails new_details(
+ static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
+ details.type(),
+ details.index());
+ function->property_dictionary()->DetailsAtPut(entry, new_details);
+ }
+ return function;
+}
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
=======================================
--- /trunk/src/runtime.h Wed Jul 20 06:44:42 2011
+++ /trunk/src/runtime.h Thu Jul 28 02:15:17 2011
@@ -210,6 +210,7 @@
F(FunctionSetInstanceClassName, 2, 1) \
F(FunctionSetLength, 2, 1) \
F(FunctionSetPrototype, 2, 1) \
+ F(FunctionSetReadOnlyPrototype, 1, 1) \
F(FunctionGetName, 1, 1) \
F(FunctionSetName, 2, 1) \
F(FunctionSetBound, 1, 1) \
=======================================
--- /trunk/src/type-info.cc Mon Jul 4 07:01:31 2011
+++ /trunk/src/type-info.cc Thu Jul 28 02:15:17 2011
@@ -437,6 +437,12 @@
}
}
}
+
+
+byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) {
+ Handle<Object> object = GetInfo(ast_id);
+ return object->IsCode() ?
Handle<Code>::cast(object)->to_boolean_state() : 0;
+}
// Things are a bit tricky here: The iterator for the RelocInfos and the
infos
@@ -523,6 +529,7 @@
case Code::UNARY_OP_IC:
case Code::BINARY_OP_IC:
case Code::COMPARE_IC:
+ case Code::TO_BOOLEAN_IC:
SetInfo(ast_id, target);
break;
=======================================
--- /trunk/src/type-info.h Wed Jul 13 06:23:34 2011
+++ /trunk/src/type-info.h Thu Jul 28 02:15:17 2011
@@ -238,6 +238,11 @@
bool LoadIsBuiltin(Property* expr, Builtins::Name id);
+ // TODO(1571) We can't use ToBooleanStub::Types as the return value
because
+ // of various cylces in our headers. Death to tons of implementations in
+ // headers!! :-P
+ byte ToBooleanTypes(unsigned ast_id);
+
// Get type information for arithmetic operations and compares.
TypeInfo UnaryType(UnaryOperation* expr);
TypeInfo BinaryType(BinaryOperation* expr);
=======================================
--- /trunk/src/version.cc Mon Jul 25 04:05:35 2011
+++ /trunk/src/version.cc Thu Jul 28 02:15:17 2011
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 5
-#define BUILD_NUMBER 0
+#define BUILD_NUMBER 1
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/x64/lithium-codegen-x64.cc Wed Jul 20 06:44:42 2011
+++ /trunk/src/x64/lithium-codegen-x64.cc Thu Jul 28 02:15:17 2011
@@ -2246,7 +2246,6 @@
void LCodeGen::DoLoadKeyedFastDoubleElement(
LLoadKeyedFastDoubleElement* instr) {
- Register elements = ToRegister(instr->elements());
XMMRegister result(ToDoubleRegister(instr->result()));
if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3101,14 +3100,11 @@
void LCodeGen::DoStoreKeyedFastDoubleElement(
LStoreKeyedFastDoubleElement* instr) {
XMMRegister value = ToDoubleRegister(instr->value());
- Register elements = ToRegister(instr->elements());
Label have_value;
__ ucomisd(value, value);
__ j(parity_odd, &have_value); // NaN.
- ExternalReference canonical_nan_reference =
- ExternalReference::address_of_canonical_non_hole_nan();
__ Set(kScratchRegister, BitCast<uint64_t>(
FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
__ movq(value, kScratchRegister);
=======================================
--- /trunk/test/benchmarks/testcfg.py Wed Mar 23 04:19:56 2011
+++ /trunk/test/benchmarks/testcfg.py Thu Jul 28 02:15:17 2011
@@ -91,7 +91,7 @@
return [test]
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
pass
=======================================
--- /trunk/test/cctest/test-api.cc Mon Jul 25 04:05:35 2011
+++ /trunk/test/cctest/test-api.cc Thu Jul 28 02:15:17 2011
@@ -7055,53 +7055,34 @@
}
-THREADED_TEST(SetPrototypeProperties) {
+THREADED_TEST(FunctionReadOnlyPrototype) {
v8::HandleScope handle_scope;
LocalContext context;
Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
- t1->SetPrototypeAttributes(v8::DontDelete);
+ t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
+ t1->ReadOnlyPrototype();
context->Global()->Set(v8_str("func1"), t1->GetFunction());
+ // Configured value of ReadOnly flag.
CHECK(CompileRun(
"(function() {"
" descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
- " return (descriptor['writable'] == true) &&"
- " (descriptor['enumerable'] == true) &&"
- " (descriptor['configurable'] == false);"
+ " return (descriptor['writable'] == false);"
"})()")->BooleanValue());
+ CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
+ CHECK_EQ(42,
+ CompileRun("func1.prototype = {};
func1.prototype.x")->Int32Value());
Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
- t2->SetPrototypeAttributes(v8::DontEnum);
+ t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
context->Global()->Set(v8_str("func2"), t2->GetFunction());
+ // Default value of ReadOnly flag.
CHECK(CompileRun(
"(function() {"
" descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
- " return (descriptor['writable'] == true) &&"
- " (descriptor['enumerable'] == false) &&"
- " (descriptor['configurable'] == true);"
+ " return (descriptor['writable'] == true);"
"})()")->BooleanValue());
-
- Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
- t3->SetPrototypeAttributes(v8::ReadOnly);
- context->Global()->Set(v8_str("func3"), t3->GetFunction());
- CHECK(CompileRun(
- "(function() {"
- " descriptor = Object.getOwnPropertyDescriptor(func3, 'prototype');"
- " return (descriptor['writable'] == false) &&"
- " (descriptor['enumerable'] == true) &&"
- " (descriptor['configurable'] == true);"
- "})()")->BooleanValue());
-
- Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
- t4->SetPrototypeAttributes(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
- context->Global()->Set(v8_str("func4"), t4->GetFunction());
- CHECK(CompileRun(
- "(function() {"
- " descriptor = Object.getOwnPropertyDescriptor(func4, 'prototype');"
- " return (descriptor['writable'] == false) &&"
- " (descriptor['enumerable'] == false) &&"
- " (descriptor['configurable'] == false);"
- "})()")->BooleanValue());
+ CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
}
=======================================
--- /trunk/test/es5conform/testcfg.py Wed Mar 23 04:19:56 2011
+++ /trunk/test/es5conform/testcfg.py Thu Jul 28 02:15:17 2011
@@ -97,7 +97,7 @@
return tests
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'es5conform.status')
=======================================
--- /trunk/test/message/testcfg.py Wed Mar 23 04:19:56 2011
+++ /trunk/test/message/testcfg.py Thu Jul 28 02:15:17 2011
@@ -125,7 +125,7 @@
return result
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'message.status')
=======================================
--- /trunk/test/mjsunit/testcfg.py Tue May 31 23:00:58 2011
+++ /trunk/test/mjsunit/testcfg.py Thu Jul 28 02:15:17 2011
@@ -145,7 +145,7 @@
return result
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'mjsunit.status')
=======================================
--- /trunk/test/mozilla/testcfg.py Wed Mar 23 04:19:56 2011
+++ /trunk/test/mozilla/testcfg.py Thu Jul 28 02:15:17 2011
@@ -125,7 +125,7 @@
return tests
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'mozilla.status')
=======================================
--- /trunk/test/sputnik/testcfg.py Mon Apr 18 08:51:38 2011
+++ /trunk/test/sputnik/testcfg.py Thu Jul 28 02:15:17 2011
@@ -101,7 +101,7 @@
return result
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'sputnik.status')
=======================================
--- /trunk/test/test262/testcfg.py Mon Mar 28 03:47:03 2011
+++ /trunk/test/test262/testcfg.py Thu Jul 28 02:15:17 2011
@@ -111,7 +111,7 @@
return tests
def GetBuildRequirements(self):
- return ['sample', 'sample=shell']
+ return ['d8']
def GetTestStatus(self, sections, defs):
status_file = join(self.root, 'test262.status')
=======================================
***Additional files exist in this changeset.***
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev