Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/interpreter/bytecode-array-builder.h b/src/interpreter/bytecode-array-builder.h
new file mode 100644
index 0000000..7c23dc3
--- /dev/null
+++ b/src/interpreter/bytecode-array-builder.h
@@ -0,0 +1,387 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
+#define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
+
+#include "src/ast/ast.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/constant-array-builder.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+
+class Isolate;
+
+namespace interpreter {
+
+class BytecodeLabel;
+class ConstantArrayBuilder;
+class Register;
+
+// TODO(rmcilroy): Unify this with CreateArgumentsParameters::Type in Turbofan
+// when rest parameters implementation has settled down.
+enum class CreateArgumentsType { kMappedArguments, kUnmappedArguments };
+
+class BytecodeArrayBuilder final {
+ public:
+  BytecodeArrayBuilder(Isolate* isolate, Zone* zone);
+  ~BytecodeArrayBuilder();
+
+  Handle<BytecodeArray> ToBytecodeArray();
+
+  // Set the number of parameters expected by function.
+  void set_parameter_count(int number_of_params);
+  int parameter_count() const {
+    DCHECK_GE(parameter_count_, 0);
+    return parameter_count_;
+  }
+
+  // Set the number of locals required for bytecode array.
+  void set_locals_count(int number_of_locals);
+  int locals_count() const {
+    DCHECK_GE(local_register_count_, 0);
+    return local_register_count_;
+  }
+
+  // Set number of contexts required for bytecode array.
+  void set_context_count(int number_of_contexts);
+  int context_count() const {
+    DCHECK_GE(context_register_count_, 0);
+    return context_register_count_;
+  }
+
+  Register first_context_register() const;
+  Register last_context_register() const;
+
+  // Returns the number of fixed (non-temporary) registers.
+  int fixed_register_count() const { return context_count() + locals_count(); }
+
+  Register Parameter(int parameter_index) const;
+
+  // Return true if the register |reg| represents a parameter or a
+  // local.
+  bool RegisterIsParameterOrLocal(Register reg) const;
+
+  // Return true if the register |reg| represents a temporary register.
+  bool RegisterIsTemporary(Register reg) const;
+
+  // Constant loads to accumulator.
+  BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
+  BytecodeArrayBuilder& LoadLiteral(Handle<Object> object);
+  BytecodeArrayBuilder& LoadUndefined();
+  BytecodeArrayBuilder& LoadNull();
+  BytecodeArrayBuilder& LoadTheHole();
+  BytecodeArrayBuilder& LoadTrue();
+  BytecodeArrayBuilder& LoadFalse();
+  BytecodeArrayBuilder& LoadBooleanConstant(bool value);
+
+  // Global loads to the accumulator and stores from the accumulator.
+  BytecodeArrayBuilder& LoadGlobal(const Handle<String> name, int feedback_slot,
+                                   LanguageMode language_mode,
+                                   TypeofMode typeof_mode);
+  BytecodeArrayBuilder& StoreGlobal(const Handle<String> name,
+                                    int feedback_slot,
+                                    LanguageMode language_mode);
+
+  // Load the object at |slot_index| in |context| into the accumulator.
+  BytecodeArrayBuilder& LoadContextSlot(Register context, int slot_index);
+
+  // Stores the object in the accumulator into |slot_index| of |context|.
+  BytecodeArrayBuilder& StoreContextSlot(Register context, int slot_index);
+
+  // Register-accumulator transfers.
+  BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
+  BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
+
+  // Register-register transfer.
+  BytecodeArrayBuilder& MoveRegister(Register from, Register to);
+  BytecodeArrayBuilder& ExchangeRegisters(Register reg0, Register reg1);
+
+  // Named load property.
+  BytecodeArrayBuilder& LoadNamedProperty(Register object,
+                                          const Handle<String> name,
+                                          int feedback_slot,
+                                          LanguageMode language_mode);
+  // Keyed load property. The key should be in the accumulator.
+  BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot,
+                                          LanguageMode language_mode);
+
+  // Store properties. The value to be stored should be in the accumulator.
+  BytecodeArrayBuilder& StoreNamedProperty(Register object,
+                                           const Handle<String> name,
+                                           int feedback_slot,
+                                           LanguageMode language_mode);
+  BytecodeArrayBuilder& StoreKeyedProperty(Register object, Register key,
+                                           int feedback_slot,
+                                           LanguageMode language_mode);
+
+  // Lookup the variable with |name|.
+  BytecodeArrayBuilder& LoadLookupSlot(const Handle<String> name,
+                                       TypeofMode typeof_mode);
+
+  // Store value in the accumulator into the variable with |name|.
+  BytecodeArrayBuilder& StoreLookupSlot(const Handle<String> name,
+                                        LanguageMode language_mode);
+
+  // Create a new closure for the SharedFunctionInfo.
+  BytecodeArrayBuilder& CreateClosure(Handle<SharedFunctionInfo> shared_info,
+                                      PretenureFlag tenured);
+
+  // Create a new arguments object in the accumulator.
+  BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
+
+  // Literals creation.  Constant elements should be in the accumulator.
+  BytecodeArrayBuilder& CreateRegExpLiteral(Handle<String> pattern,
+                                            int literal_index, int flags);
+  BytecodeArrayBuilder& CreateArrayLiteral(Handle<FixedArray> constant_elements,
+                                           int literal_index, int flags);
+  BytecodeArrayBuilder& CreateObjectLiteral(
+      Handle<FixedArray> constant_properties, int literal_index, int flags);
+
+  // Push the context in accumulator as the new context, and store in register
+  // |context|.
+  BytecodeArrayBuilder& PushContext(Register context);
+
+  // Pop the current context and replace with |context|.
+  BytecodeArrayBuilder& PopContext(Register context);
+
+  // Call a JS function. The JSFunction or Callable to be called should be in
+  // |callable|, the receiver should be in |receiver| and all subsequent
+  // arguments should be in registers <receiver + 1> to
+  // <receiver + 1 + arg_count>.
+  BytecodeArrayBuilder& Call(Register callable, Register receiver,
+                             size_t arg_count, int feedback_slot);
+
+  // Call the new operator. The |constructor| register is followed by
+  // |arg_count| consecutive registers containing arguments to be
+  // applied to the constructor.
+  BytecodeArrayBuilder& New(Register constructor, Register first_arg,
+                            size_t arg_count);
+
+  // Call the runtime function with |function_id|. The first argument should be
+  // in |first_arg| and all subsequent arguments should be in registers
+  // <first_arg + 1> to <first_arg + 1 + arg_count>.
+  BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
+                                    Register first_arg, size_t arg_count);
+
+  // Call the runtime function with |function_id| that returns a pair of values.
+  // The first argument should be in |first_arg| and all subsequent arguments
+  // should be in registers <first_arg + 1> to <first_arg + 1 + arg_count>. The
+  // return values will be returned in <first_return> and <first_return + 1>.
+  BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
+                                           Register first_arg, size_t arg_count,
+                                           Register first_return);
+
+  // Call the JS runtime function with |context_index|. The the receiver should
+  // be in |receiver| and all subsequent arguments should be in registers
+  // <receiver + 1> to <receiver + 1 + arg_count>.
+  BytecodeArrayBuilder& CallJSRuntime(int context_index, Register receiver,
+                                      size_t arg_count);
+
+  // Operators (register holds the lhs value, accumulator holds the rhs value).
+  BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
+                                        Strength strength);
+
+  // Count Operators (value stored in accumulator).
+  BytecodeArrayBuilder& CountOperation(Token::Value op, Strength strength);
+
+  // Unary Operators.
+  BytecodeArrayBuilder& LogicalNot();
+  BytecodeArrayBuilder& TypeOf();
+
+  // Deletes property from an object. This expects that accumulator contains
+  // the key to be deleted and the register contains a reference to the object.
+  BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
+  BytecodeArrayBuilder& DeleteLookupSlot();
+
+  // Tests.
+  BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
+                                         Strength strength);
+
+  // Casts.
+  BytecodeArrayBuilder& CastAccumulatorToBoolean();
+  BytecodeArrayBuilder& CastAccumulatorToJSObject();
+  BytecodeArrayBuilder& CastAccumulatorToName();
+  BytecodeArrayBuilder& CastAccumulatorToNumber();
+
+  // Flow Control.
+  BytecodeArrayBuilder& Bind(BytecodeLabel* label);
+  BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
+
+  BytecodeArrayBuilder& Jump(BytecodeLabel* label);
+  BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label);
+  BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
+  BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
+  BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
+
+  BytecodeArrayBuilder& Throw();
+  BytecodeArrayBuilder& Return();
+
+  // Complex flow control.
+  BytecodeArrayBuilder& ForInPrepare(Register cache_type, Register cache_array,
+                                     Register cache_length);
+  BytecodeArrayBuilder& ForInDone(Register index, Register cache_length);
+  BytecodeArrayBuilder& ForInNext(Register receiver, Register cache_type,
+                                  Register cache_array, Register index);
+  BytecodeArrayBuilder& ForInStep(Register index);
+
+  // Accessors
+  Zone* zone() const { return zone_; }
+
+ private:
+  ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; }
+  const ZoneVector<uint8_t>* bytecodes() const { return &bytecodes_; }
+  Isolate* isolate() const { return isolate_; }
+  ConstantArrayBuilder* constant_array_builder() {
+    return &constant_array_builder_;
+  }
+  const ConstantArrayBuilder* constant_array_builder() const {
+    return &constant_array_builder_;
+  }
+
+  static Bytecode BytecodeForBinaryOperation(Token::Value op);
+  static Bytecode BytecodeForCountOperation(Token::Value op);
+  static Bytecode BytecodeForCompareOperation(Token::Value op);
+  static Bytecode BytecodeForWideOperands(Bytecode bytecode);
+  static Bytecode BytecodeForLoadIC(LanguageMode language_mode);
+  static Bytecode BytecodeForKeyedLoadIC(LanguageMode language_mode);
+  static Bytecode BytecodeForStoreIC(LanguageMode language_mode);
+  static Bytecode BytecodeForKeyedStoreIC(LanguageMode language_mode);
+  static Bytecode BytecodeForLoadGlobal(LanguageMode language_mode,
+                                        TypeofMode typeof_mode);
+  static Bytecode BytecodeForStoreGlobal(LanguageMode language_mode);
+  static Bytecode BytecodeForStoreLookupSlot(LanguageMode language_mode);
+  static Bytecode BytecodeForCreateArguments(CreateArgumentsType type);
+  static Bytecode BytecodeForDelete(LanguageMode language_mode);
+
+  static bool FitsInIdx8Operand(int value);
+  static bool FitsInIdx8Operand(size_t value);
+  static bool FitsInImm8Operand(int value);
+  static bool FitsInIdx16Operand(int value);
+  static bool FitsInIdx16Operand(size_t value);
+  static bool FitsInReg8Operand(Register value);
+  static bool FitsInReg16Operand(Register value);
+
+  static Bytecode GetJumpWithConstantOperand(Bytecode jump_smi8_operand);
+  static Bytecode GetJumpWithConstantWideOperand(Bytecode jump_smi8_operand);
+  static Bytecode GetJumpWithToBoolean(Bytecode jump_smi8_operand);
+
+  Register MapRegister(Register reg);
+  Register MapRegisters(Register reg, Register args_base, int args_length = 1);
+
+  template <size_t N>
+  INLINE(void Output(Bytecode bytecode, uint32_t(&operands)[N]));
+  void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+              uint32_t operand2, uint32_t operand3);
+  void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+              uint32_t operand2);
+  void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
+  void Output(Bytecode bytecode, uint32_t operand0);
+  void Output(Bytecode bytecode);
+
+  BytecodeArrayBuilder& OutputJump(Bytecode jump_bytecode,
+                                   BytecodeLabel* label);
+  void PatchJump(const ZoneVector<uint8_t>::iterator& jump_target,
+                 const ZoneVector<uint8_t>::iterator& jump_location);
+  void PatchIndirectJumpWith8BitOperand(
+      const ZoneVector<uint8_t>::iterator& jump_location, int delta);
+  void PatchIndirectJumpWith16BitOperand(
+      const ZoneVector<uint8_t>::iterator& jump_location, int delta);
+
+  void LeaveBasicBlock();
+  void EnsureReturn();
+
+  bool OperandIsValid(Bytecode bytecode, int operand_index,
+                      uint32_t operand_value) const;
+  bool LastBytecodeInSameBlock() const;
+
+  bool NeedToBooleanCast();
+  bool IsRegisterInAccumulator(Register reg);
+
+  bool RegisterIsValid(Register reg) const;
+
+  // Temporary register management.
+  int BorrowTemporaryRegister();
+  int BorrowTemporaryRegisterNotInRange(int start_index, int end_index);
+  void ReturnTemporaryRegister(int reg_index);
+  int PrepareForConsecutiveTemporaryRegisters(size_t count);
+  void BorrowConsecutiveTemporaryRegister(int reg_index);
+  bool TemporaryRegisterIsLive(Register reg) const;
+
+  Register first_temporary_register() const;
+  Register last_temporary_register() const;
+
+  // Gets a constant pool entry for the |object|.
+  size_t GetConstantPoolEntry(Handle<Object> object);
+
+  Isolate* isolate_;
+  Zone* zone_;
+  ZoneVector<uint8_t> bytecodes_;
+  bool bytecode_generated_;
+  ConstantArrayBuilder constant_array_builder_;
+  size_t last_block_end_;
+  size_t last_bytecode_start_;
+  bool exit_seen_in_block_;
+  int unbound_jumps_;
+
+  int parameter_count_;
+  int local_register_count_;
+  int context_register_count_;
+  int temporary_register_count_;
+  ZoneSet<int> free_temporaries_;
+
+  class PreviousBytecodeHelper;
+  friend class BytecodeRegisterAllocator;
+
+  DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
+};
+
+
+// A label representing a branch target in a bytecode array. When a
+// label is bound, it represents a known position in the bytecode
+// array. For labels that are forward references there can be at most
+// one reference whilst it is unbound.
+class BytecodeLabel final {
+ public:
+  BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {}
+
+  bool is_bound() const { return bound_; }
+  size_t offset() const { return offset_; }
+
+ private:
+  static const size_t kInvalidOffset = static_cast<size_t>(-1);
+
+  void bind_to(size_t offset) {
+    DCHECK(!bound_ && offset != kInvalidOffset);
+    offset_ = offset;
+    bound_ = true;
+  }
+
+  void set_referrer(size_t offset) {
+    DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset);
+    offset_ = offset;
+  }
+
+  bool is_forward_target() const {
+    return offset() != kInvalidOffset && !is_bound();
+  }
+
+  // There are three states for a label:
+  //                    bound_   offset_
+  //  UNSET             false    kInvalidOffset
+  //  FORWARD_TARGET    false    Offset of referring jump
+  //  BACKWARD_TARGET    true    Offset of label in bytecode array when bound
+  bool bound_;
+  size_t offset_;
+
+  friend class BytecodeArrayBuilder;
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_