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

Reply via email to