Merge branch 'v0.10'
authorFedor Indutny <fedor.indutny@gmail.com>
Fri, 13 Dec 2013 23:03:50 +0000 (03:03 +0400)
committerFedor Indutny <fedor.indutny@gmail.com>
Fri, 13 Dec 2013 23:03:50 +0000 (03:03 +0400)
Conflicts:
deps/v8/src/elements-kind.cc
deps/v8/src/elements-kind.h
deps/v8/src/hydrogen-instructions.h
deps/v8/src/hydrogen.cc
deps/v8/src/lithium.cc
deps/v8/src/lithium.h

1  2 
deps/v8/src/elements-kind.cc
deps/v8/src/elements-kind.h
deps/v8/src/hydrogen-dehoist.cc
deps/v8/src/hydrogen-instructions.h
deps/v8/src/lithium.cc
deps/v8/src/lithium.h

@@@ -35,14 -35,39 +35,44 @@@ namespace v8 
  namespace internal {
  
  
 -void PrintElementsKind(FILE* out, ElementsKind kind) {
+ int ElementsKindToShiftSize(ElementsKind elements_kind) {
+   switch (elements_kind) {
+     case EXTERNAL_BYTE_ELEMENTS:
+     case EXTERNAL_PIXEL_ELEMENTS:
+     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+       return 0;
+     case EXTERNAL_SHORT_ELEMENTS:
+     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+       return 1;
+     case EXTERNAL_INT_ELEMENTS:
+     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+     case EXTERNAL_FLOAT_ELEMENTS:
+       return 2;
+     case EXTERNAL_DOUBLE_ELEMENTS:
+     case FAST_DOUBLE_ELEMENTS:
+     case FAST_HOLEY_DOUBLE_ELEMENTS:
+       return 3;
+     case FAST_SMI_ELEMENTS:
+     case FAST_ELEMENTS:
+     case FAST_HOLEY_SMI_ELEMENTS:
+     case FAST_HOLEY_ELEMENTS:
+     case DICTIONARY_ELEMENTS:
+     case NON_STRICT_ARGUMENTS_ELEMENTS:
+       return kPointerSizeLog2;
+   }
+   UNREACHABLE();
+   return 0;
+ }
 +const char* ElementsKindToString(ElementsKind kind) {
    ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
 -  PrintF(out, "%s", accessor->name());
 +  return accessor->name();
 +}
 +
 +
 +void PrintElementsKind(FILE* out, ElementsKind kind) {
 +  PrintF(out, "%s", ElementsKindToString(kind));
  }
  
  
@@@ -77,7 -77,8 +77,8 @@@ const int kElementsKindCount = LAST_ELE
  const int kFastElementsKindCount = LAST_FAST_ELEMENTS_KIND -
      FIRST_FAST_ELEMENTS_KIND + 1;
  
 -
+ int ElementsKindToShiftSize(ElementsKind elements_kind);
 +const char* ElementsKindToString(ElementsKind kind);
  void PrintElementsKind(FILE* out, ElementsKind kind);
  
  ElementsKind GetInitialFastElementsKind();
index 67e6718,0000000..bdf2cfb
mode 100644,000000..100644
--- /dev/null
@@@ -1,80 -1,0 +1,80 @@@
-   if (value >= 1 << 30 || value < 0) return;
 +// Copyright 2013 the V8 project authors. All rights reserved.
 +// Redistribution and use in source and binary forms, with or without
 +// modification, are permitted provided that the following conditions are
 +// met:
 +//
 +//     * Redistributions of source code must retain the above copyright
 +//       notice, this list of conditions and the following disclaimer.
 +//     * Redistributions in binary form must reproduce the above
 +//       copyright notice, this list of conditions and the following
 +//       disclaimer in the documentation and/or other materials provided
 +//       with the distribution.
 +//     * Neither the name of Google Inc. nor the names of its
 +//       contributors may be used to endorse or promote products derived
 +//       from this software without specific prior written permission.
 +//
 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 +
 +#include "hydrogen-dehoist.h"
 +
 +namespace v8 {
 +namespace internal {
 +
 +static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
 +  HValue* index = array_operation->GetKey()->ActualValue();
 +  if (!index->representation().IsSmiOrInteger32()) return;
 +  if (!index->IsAdd() && !index->IsSub()) return;
 +
 +  HConstant* constant;
 +  HValue* subexpression;
 +  HBinaryOperation* binary_operation = HBinaryOperation::cast(index);
 +  if (binary_operation->left()->IsConstant() && index->IsAdd()) {
 +    subexpression = binary_operation->right();
 +    constant = HConstant::cast(binary_operation->left());
 +  } else if (binary_operation->right()->IsConstant()) {
 +    subexpression = binary_operation->left();
 +    constant = HConstant::cast(binary_operation->right());
 +  } else {
 +    return;
 +  }
 +
 +  if (!constant->HasInteger32Value()) return;
 +  int32_t sign = binary_operation->IsSub() ? -1 : 1;
 +  int32_t value = constant->Integer32Value() * sign;
 +  // We limit offset values to 30 bits because we want to avoid the risk of
 +  // overflows when the offset is added to the object header size.
++  if (value >= 1 << array_operation->MaxIndexOffsetBits() || value < 0) return;
 +  array_operation->SetKey(subexpression);
 +  if (binary_operation->HasNoUses()) {
 +    binary_operation->DeleteAndReplaceWith(NULL);
 +  }
 +  array_operation->SetIndexOffset(static_cast<uint32_t>(value));
 +  array_operation->SetDehoisted(true);
 +}
 +
 +
 +void HDehoistIndexComputationsPhase::Run() {
 +  const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
 +  for (int i = 0; i < blocks->length(); ++i) {
 +    for (HInstructionIterator it(blocks->at(i)); !it.Done(); it.Advance()) {
 +      HInstruction* instr = it.Current();
 +      if (instr->IsLoadKeyed()) {
 +        DehoistArrayIndex(HLoadKeyed::cast(instr));
 +      } else if (instr->IsStoreKeyed()) {
 +        DehoistArrayIndex(HStoreKeyed::cast(instr));
 +      }
 +    }
 +  }
 +}
 +
 +} }  // namespace v8::internal
@@@ -6011,129 -4318,43 +6011,133 @@@ class HLoadNamedField V8_FINAL : publi
  };
  
  
 -enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
 +class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> {
 + public:
 +  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
 +                                              Handle<Object>);
  
 +  HValue* context() { return OperandAt(0); }
 +  HValue* object() { return OperandAt(1); }
 +  Handle<Object> name() const { return name_; }
  
 -class HLoadKeyedFastDoubleElement
 -    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
 +  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
 +    return Representation::Tagged();
 +  }
 +
 +  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
 +
 +  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
 +
 + private:
 +  HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
 +      : name_(name) {
 +    SetOperandAt(0, context);
 +    SetOperandAt(1, object);
 +    set_representation(Representation::Tagged());
 +    SetAllSideEffects();
 +  }
 +
 +  Handle<Object> name_;
 +};
 +
 +
 +class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
   public:
 -  HLoadKeyedFastDoubleElement(
 -    HValue* elements,
 -    HValue* key,
 -    HValue* dependency,
 -    HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
 -      : index_offset_(0),
 -        is_dehoisted_(false),
 -        hole_check_mode_(hole_check_mode) {
 -    SetOperandAt(0, elements);
 -    SetOperandAt(1, key);
 -    SetOperandAt(2, dependency);
 -    set_representation(Representation::Double());
 -    SetGVNFlag(kDependsOnDoubleArrayElements);
 +  DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
 +
 +  HValue* function() { return OperandAt(0); }
 +
 +  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
 +    return Representation::Tagged();
 +  }
 +
 +  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
 +
 + protected:
 +  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
 +
 + private:
 +  explicit HLoadFunctionPrototype(HValue* function)
 +      : HUnaryOperation(function) {
 +    set_representation(Representation::Tagged());
      SetFlag(kUseGVN);
 +    SetGVNFlag(kDependsOnCalls);
    }
 +};
 +
 +class ArrayInstructionInterface {
 + public:
 +  virtual HValue* GetKey() = 0;
 +  virtual void SetKey(HValue* key) = 0;
 +  virtual void SetIndexOffset(uint32_t index_offset) = 0;
++  virtual int MaxIndexOffsetBits() = 0;
 +  virtual bool IsDehoisted() = 0;
 +  virtual void SetDehoisted(bool is_dehoisted) = 0;
 +  virtual ~ArrayInstructionInterface() { };
  
 +  static Representation KeyedAccessIndexRequirement(Representation r) {
 +    return r.IsInteger32() || SmiValuesAre32Bits()
 +        ? Representation::Integer32() : Representation::Smi();
 +  }
 +};
 +
 +
 +enum LoadKeyedHoleMode {
 +  NEVER_RETURN_HOLE,
 +  ALLOW_RETURN_HOLE
 +};
 +
 +
 +class HLoadKeyed V8_FINAL
 +    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
 + public:
 +  DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
 +                                 ElementsKind);
 +  DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
 +                                 ElementsKind, LoadKeyedHoleMode);
 +
 +  bool is_external() const {
 +    return IsExternalArrayElementsKind(elements_kind());
 +  }
    HValue* elements() { return OperandAt(0); }
    HValue* key() { return OperandAt(1); }
 -  HValue* dependency() { return OperandAt(2); }
 -  uint32_t index_offset() { return index_offset_; }
 -  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
 -  int MaxIndexOffsetBits() { return 25; }
 +  HValue* dependency() {
 +    ASSERT(HasDependency());
 +    return OperandAt(2);
 +  }
 +  bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
 +  uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
 +  void SetIndexOffset(uint32_t index_offset) {
 +    bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
 +  }
++  virtual int MaxIndexOffsetBits() {
++    return kBitsForIndexOffset;
++  }
    HValue* GetKey() { return key(); }
    void SetKey(HValue* key) { SetOperandAt(1, key); }
 -  bool IsDehoisted() { return is_dehoisted_; }
 -  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
 +  bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
 +  void SetDehoisted(bool is_dehoisted) {
 +    bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
 +  }
 +  ElementsKind elements_kind() const {
 +    return ElementsKindField::decode(bit_field_);
 +  }
 +  LoadKeyedHoleMode hole_mode() const {
 +    return HoleModeField::decode(bit_field_);
 +  }
  
 -  virtual Representation RequiredInputRepresentation(int index) {
 -    // The key is supposed to be Integer32.
 -    if (index == 0) return Representation::Tagged();
 -    if (index == 1) return Representation::Integer32();
 +  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
 +    // kind_fast:       tagged[int32] (none)
 +    // kind_double:     tagged[int32] (none)
 +    // kind_external: external[int32] (none)
 +    if (index == 0) {
 +      return is_external() ? Representation::External()
 +          : Representation::Tagged();
 +    }
 +    if (index == 1) {
 +      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
 +          OperandAt(1)->representation());
 +    }
      return Representation::None();
    }
  
@@@ -6486,12 -4651,9 +6490,15 @@@ class HStoreKeyed V8_FINA
    HValue* elements() { return OperandAt(0); }
    HValue* key() { return OperandAt(1); }
    HValue* value() { return OperandAt(2); }
 +  bool value_is_smi() const {
 +    return IsFastSmiElementsKind(elements_kind_);
 +  }
 +  ElementsKind elements_kind() const { return elements_kind_; }
    uint32_t index_offset() { return index_offset_; }
    void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
 -  int MaxIndexOffsetBits() { return 25; }
++  virtual int MaxIndexOffsetBits() {
++    return 31 - ElementsKindToShiftSize(elements_kind_);
++  }
    HValue* GetKey() { return key(); }
    void SetKey(HValue* key) { SetOperandAt(1, key); }
    bool IsDehoisted() { return is_dehoisted_; }
@@@ -229,59 -223,7 +229,29 @@@ void LPointerMap::PrintTo(StringStream
      if (i != 0) stream->Add(";");
      pointer_operands_[i]->PrintTo(stream);
    }
 -  stream->Add("} @%d", position());
 +  stream->Add("}");
 +}
 +
 +
- int ElementsKindToShiftSize(ElementsKind elements_kind) {
-   switch (elements_kind) {
-     case EXTERNAL_BYTE_ELEMENTS:
-     case EXTERNAL_PIXEL_ELEMENTS:
-     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-       return 0;
-     case EXTERNAL_SHORT_ELEMENTS:
-     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-       return 1;
-     case EXTERNAL_INT_ELEMENTS:
-     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-     case EXTERNAL_FLOAT_ELEMENTS:
-       return 2;
-     case EXTERNAL_DOUBLE_ELEMENTS:
-     case FAST_DOUBLE_ELEMENTS:
-     case FAST_HOLEY_DOUBLE_ELEMENTS:
-       return 3;
-     case FAST_SMI_ELEMENTS:
-     case FAST_ELEMENTS:
-     case FAST_HOLEY_SMI_ELEMENTS:
-     case FAST_HOLEY_ELEMENTS:
-     case DICTIONARY_ELEMENTS:
-     case NON_STRICT_ARGUMENTS_ELEMENTS:
-       return kPointerSizeLog2;
-   }
-   UNREACHABLE();
-   return 0;
- }
 +int StackSlotOffset(int index) {
 +  if (index >= 0) {
 +    // Local or spill slot. Skip the frame pointer, function, and
 +    // context in the fixed part of the frame.
 +    return -(index + 3) * kPointerSize;
 +  } else {
 +    // Incoming parameter. Skip the return address.
 +    return -(index + 1) * kPointerSize + kFPOnStackSize + kPCOnStackSize;
 +  }
 +}
 +
 +
 +LChunk::LChunk(CompilationInfo* info, HGraph* graph)
 +    : spill_slot_count_(0),
 +      info_(info),
 +      graph_(graph),
 +      instructions_(32, graph->zone()),
 +      pointer_maps_(8, graph->zone()),
 +      inlined_closures_(1, graph->zone()) {
  }
  
  
@@@ -791,29 -704,6 +791,28 @@@ class LChunk : public ZoneObject 
  };
  
  
- int ElementsKindToShiftSize(ElementsKind elements_kind);
 +int StackSlotOffset(int index);
 +
 +enum NumberUntagDMode {
 +  NUMBER_CANDIDATE_IS_SMI,
 +  NUMBER_CANDIDATE_IS_ANY_TAGGED
 +};
 +
 +
 +class LPhase : public CompilationPhase {
 + public:
 +  LPhase(const char* name, LChunk* chunk)
 +      : CompilationPhase(name, chunk->info()),
 +        chunk_(chunk) { }
 +  ~LPhase();
 +
 + private:
 +  LChunk* chunk_;
 +
 +  DISALLOW_COPY_AND_ASSIGN(LPhase);
 +};
 +
 +
  } }  // namespace v8::internal
  
  #endif  // V8_LITHIUM_H_