// Copyright 2012 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_COMPILER_H_
#define V8_COMPILER_H_

#include "src/allocation.h"
#include "src/ast.h"
#include "src/zone.h"

namespace v8 {
namespace internal {

class AstValueFactory;
class HydrogenCodeStub;

// ParseRestriction is used to restrict the set of valid statements in a
// unit of compilation.  Restriction violations cause a syntax error.
enum ParseRestriction {
  NO_PARSE_RESTRICTION,         // All expressions are allowed.
  ONLY_SINGLE_FUNCTION_LITERAL  // Only a single FunctionLiteral expression.
};

struct OffsetRange {
  OffsetRange(int from, int to) : from(from), to(to) {}
  int from;
  int to;
};


class ScriptData {
 public:
  ScriptData(const byte* data, int length);
  ~ScriptData() {
    if (owns_data_) DeleteArray(data_);
  }

  const byte* data() const { return data_; }
  int length() const { return length_; }

  void AcquireDataOwnership() {
    DCHECK(!owns_data_);
    owns_data_ = true;
  }

  void ReleaseDataOwnership() {
    DCHECK(owns_data_);
    owns_data_ = false;
  }

 private:
  bool owns_data_;
  const byte* data_;
  int length_;

  DISALLOW_COPY_AND_ASSIGN(ScriptData);
};


// CompilationInfo encapsulates some information known at compile time.  It
// is constructed based on the resources available at compile-time.
class CompilationInfo {
 public:
  CompilationInfo(Handle<JSFunction> closure, Zone* zone);
  CompilationInfo(Isolate* isolate, Zone* zone);
  virtual ~CompilationInfo();

  Isolate* isolate() const {
    return isolate_;
  }
  Zone* zone() { return zone_; }
  bool is_osr() const { return !osr_ast_id_.IsNone(); }
  bool is_lazy() const { return IsLazy::decode(flags_); }
  bool is_eval() const { return IsEval::decode(flags_); }
  bool is_global() const { return IsGlobal::decode(flags_); }
  StrictMode strict_mode() const { return StrictModeField::decode(flags_); }
  FunctionLiteral* function() const { return function_; }
  Scope* scope() const { return scope_; }
  Scope* global_scope() const { return global_scope_; }
  Handle<Code> code() const { return code_; }
  Handle<JSFunction> closure() const { return closure_; }
  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
  Handle<Script> script() const { return script_; }
  HydrogenCodeStub* code_stub() const {return code_stub_; }
  v8::Extension* extension() const { return extension_; }
  ScriptData** cached_data() const { return cached_data_; }
  ScriptCompiler::CompileOptions compile_options() const {
    return compile_options_;
  }
  Handle<Context> context() const { return context_; }
  BailoutId osr_ast_id() const { return osr_ast_id_; }
  Handle<Code> unoptimized_code() const { return unoptimized_code_; }
  int opt_count() const { return opt_count_; }
  int num_parameters() const;
  int num_heap_slots() const;
  Code::Flags flags() const;

  void MarkAsEval() {
    DCHECK(!is_lazy());
    flags_ |= IsEval::encode(true);
  }

  void MarkAsGlobal() {
    DCHECK(!is_lazy());
    flags_ |= IsGlobal::encode(true);
  }

  void set_parameter_count(int parameter_count) {
    DCHECK(IsStub());
    parameter_count_ = parameter_count;
  }

  void set_this_has_uses(bool has_no_uses) {
    this_has_uses_ = has_no_uses;
  }

  bool this_has_uses() {
    return this_has_uses_;
  }

  void SetStrictMode(StrictMode strict_mode) {
    DCHECK(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode);
    flags_ = StrictModeField::update(flags_, strict_mode);
  }

  void MarkAsNative() {
    flags_ |= IsNative::encode(true);
  }

  bool is_native() const {
    return IsNative::decode(flags_);
  }

  bool is_calling() const {
    return is_deferred_calling() || is_non_deferred_calling();
  }

  void MarkAsDeferredCalling() {
    flags_ |= IsDeferredCalling::encode(true);
  }

  bool is_deferred_calling() const {
    return IsDeferredCalling::decode(flags_);
  }

  void MarkAsNonDeferredCalling() {
    flags_ |= IsNonDeferredCalling::encode(true);
  }

  bool is_non_deferred_calling() const {
    return IsNonDeferredCalling::decode(flags_);
  }

  void MarkAsSavesCallerDoubles() {
    flags_ |= SavesCallerDoubles::encode(true);
  }

  bool saves_caller_doubles() const {
    return SavesCallerDoubles::decode(flags_);
  }

  void MarkAsRequiresFrame() {
    flags_ |= RequiresFrame::encode(true);
  }

  bool requires_frame() const {
    return RequiresFrame::decode(flags_);
  }

  void MarkMustNotHaveEagerFrame() {
    flags_ |= MustNotHaveEagerFrame::encode(true);
  }

  bool GetMustNotHaveEagerFrame() const {
    return MustNotHaveEagerFrame::decode(flags_);
  }

  void MarkAsDebug() {
    flags_ |= IsDebug::encode(true);
  }

  bool is_debug() const {
    return IsDebug::decode(flags_);
  }

  void PrepareForSerializing() {
    flags_ |= PrepareForSerializing::encode(true);
  }

  bool will_serialize() const { return PrepareForSerializing::decode(flags_); }

  bool IsCodePreAgingActive() const {
    return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
           !is_debug();
  }

  void SetParseRestriction(ParseRestriction restriction) {
    flags_ = ParseRestricitonField::update(flags_, restriction);
  }

  ParseRestriction parse_restriction() const {
    return ParseRestricitonField::decode(flags_);
  }

  void SetFunction(FunctionLiteral* literal) {
    DCHECK(function_ == NULL);
    function_ = literal;
  }
  void PrepareForCompilation(Scope* scope);
  void SetGlobalScope(Scope* global_scope) {
    DCHECK(global_scope_ == NULL);
    global_scope_ = global_scope;
  }
  Handle<FixedArray> feedback_vector() const {
    return feedback_vector_;
  }
  void SetCode(Handle<Code> code) { code_ = code; }
  void SetExtension(v8::Extension* extension) {
    DCHECK(!is_lazy());
    extension_ = extension;
  }
  void SetCachedData(ScriptData** cached_data,
                     ScriptCompiler::CompileOptions compile_options) {
    compile_options_ = compile_options;
    if (compile_options == ScriptCompiler::kNoCompileOptions) {
      cached_data_ = NULL;
    } else {
      DCHECK(!is_lazy());
      cached_data_ = cached_data;
    }
  }
  void SetContext(Handle<Context> context) {
    context_ = context;
  }

  void MarkCompilingForDebugging() {
    flags_ |= IsCompilingForDebugging::encode(true);
  }
  bool IsCompilingForDebugging() {
    return IsCompilingForDebugging::decode(flags_);
  }
  void MarkNonOptimizable() {
    SetMode(CompilationInfo::NONOPT);
  }

  bool ShouldTrapOnDeopt() const {
    return (FLAG_trap_on_deopt && IsOptimizing()) ||
        (FLAG_trap_on_stub_deopt && IsStub());
  }

  bool has_global_object() const {
    return !closure().is_null() &&
        (closure()->context()->global_object() != NULL);
  }

  GlobalObject* global_object() const {
    return has_global_object() ? closure()->context()->global_object() : NULL;
  }

  // Accessors for the different compilation modes.
  bool IsOptimizing() const { return mode_ == OPTIMIZE; }
  bool IsOptimizable() const { return mode_ == BASE; }
  bool IsStub() const { return mode_ == STUB; }
  void SetOptimizing(BailoutId osr_ast_id, Handle<Code> unoptimized) {
    DCHECK(!shared_info_.is_null());
    SetMode(OPTIMIZE);
    osr_ast_id_ = osr_ast_id;
    unoptimized_code_ = unoptimized;
    optimization_id_ = isolate()->NextOptimizationId();
  }
  void DisableOptimization();

  // Deoptimization support.
  bool HasDeoptimizationSupport() const {
    return SupportsDeoptimization::decode(flags_);
  }
  void EnableDeoptimizationSupport() {
    DCHECK(IsOptimizable());
    flags_ |= SupportsDeoptimization::encode(true);
  }

  // Determines whether or not to insert a self-optimization header.
  bool ShouldSelfOptimize();

  void set_deferred_handles(DeferredHandles* deferred_handles) {
    DCHECK(deferred_handles_ == NULL);
    deferred_handles_ = deferred_handles;
  }

  ZoneList<Handle<HeapObject> >* dependencies(
      DependentCode::DependencyGroup group) {
    if (dependencies_[group] == NULL) {
      dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_);
    }
    return dependencies_[group];
  }

  void CommitDependencies(Handle<Code> code);

  void RollbackDependencies();

  void SaveHandles() {
    SaveHandle(&closure_);
    SaveHandle(&shared_info_);
    SaveHandle(&context_);
    SaveHandle(&script_);
    SaveHandle(&unoptimized_code_);
  }

  BailoutReason bailout_reason() const { return bailout_reason_; }
  void set_bailout_reason(BailoutReason reason) { bailout_reason_ = reason; }

  int prologue_offset() const {
    DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
    return prologue_offset_;
  }

  void set_prologue_offset(int prologue_offset) {
    DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
    prologue_offset_ = prologue_offset;
  }

  // Adds offset range [from, to) where fp register does not point
  // to the current frame base. Used in CPU profiler to detect stack
  // samples where top frame is not set up.
  inline void AddNoFrameRange(int from, int to) {
    if (no_frame_ranges_) no_frame_ranges_->Add(OffsetRange(from, to));
  }

  List<OffsetRange>* ReleaseNoFrameRanges() {
    List<OffsetRange>* result = no_frame_ranges_;
    no_frame_ranges_ = NULL;
    return result;
  }

  Handle<Foreign> object_wrapper() {
    if (object_wrapper_.is_null()) {
      object_wrapper_ =
          isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
    }
    return object_wrapper_;
  }

  void AbortDueToDependencyChange() {
    DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
    abort_due_to_dependency_ = true;
  }

  bool HasAbortedDueToDependencyChange() {
    DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
    return abort_due_to_dependency_;
  }

  bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
    return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure_);
  }

  int optimization_id() const { return optimization_id_; }

  AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
  void SetAstValueFactory(AstValueFactory* ast_value_factory,
                          bool owned = true) {
    ast_value_factory_ = ast_value_factory;
    ast_value_factory_owned_ = owned;
  }

 protected:
  CompilationInfo(Handle<Script> script,
                  Zone* zone);
  CompilationInfo(Handle<SharedFunctionInfo> shared_info,
                  Zone* zone);
  CompilationInfo(HydrogenCodeStub* stub,
                  Isolate* isolate,
                  Zone* zone);

 private:
  Isolate* isolate_;

  // Compilation mode.
  // BASE is generated by the full codegen, optionally prepared for bailouts.
  // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
  // NONOPT is generated by the full codegen and is not prepared for
  //   recompilation/bailouts.  These functions are never recompiled.
  enum Mode {
    BASE,
    OPTIMIZE,
    NONOPT,
    STUB
  };

  void Initialize(Isolate* isolate, Mode mode, Zone* zone);

  void SetMode(Mode mode) {
    mode_ = mode;
  }

  // Flags using template class BitField<type, start, length>.  All are
  // false by default.
  //
  // Compilation is either eager or lazy.
  class IsLazy:   public BitField<bool, 0, 1> {};
  // Flags that can be set for eager compilation.
  class IsEval:   public BitField<bool, 1, 1> {};
  class IsGlobal: public BitField<bool, 2, 1> {};
  // If the function is being compiled for the debugger.
  class IsDebug: public BitField<bool, 3, 1> {};
  // Strict mode - used in eager compilation.
  class StrictModeField: public BitField<StrictMode, 4, 1> {};
  // Is this a function from our natives.
  class IsNative: public BitField<bool, 5, 1> {};
  // Is this code being compiled with support for deoptimization..
  class SupportsDeoptimization: public BitField<bool, 6, 1> {};
  // If compiling for debugging produce just full code matching the
  // initial mode setting.
  class IsCompilingForDebugging: public BitField<bool, 7, 1> {};
  // If the compiled code contains calls that require building a frame
  class IsCalling: public BitField<bool, 8, 1> {};
  // If the compiled code contains calls that require building a frame
  class IsDeferredCalling: public BitField<bool, 9, 1> {};
  // If the compiled code contains calls that require building a frame
  class IsNonDeferredCalling: public BitField<bool, 10, 1> {};
  // If the compiled code saves double caller registers that it clobbers.
  class SavesCallerDoubles: public BitField<bool, 11, 1> {};
  // If the set of valid statements is restricted.
  class ParseRestricitonField: public BitField<ParseRestriction, 12, 1> {};
  // If the function requires a frame (for unspecified reasons)
  class RequiresFrame: public BitField<bool, 13, 1> {};
  // If the function cannot build a frame (for unspecified reasons)
  class MustNotHaveEagerFrame: public BitField<bool, 14, 1> {};
  // If we plan to serialize the compiled code.
  class PrepareForSerializing : public BitField<bool, 15, 1> {};

  unsigned flags_;

  // Fields filled in by the compilation pipeline.
  // AST filled in by the parser.
  FunctionLiteral* function_;
  // The scope of the function literal as a convenience.  Set to indicate
  // that scopes have been analyzed.
  Scope* scope_;
  // The global scope provided as a convenience.
  Scope* global_scope_;
  // For compiled stubs, the stub object
  HydrogenCodeStub* code_stub_;
  // The compiled code.
  Handle<Code> code_;

  // Possible initial inputs to the compilation process.
  Handle<JSFunction> closure_;
  Handle<SharedFunctionInfo> shared_info_;
  Handle<Script> script_;

  // Fields possibly needed for eager compilation, NULL by default.
  v8::Extension* extension_;
  ScriptData** cached_data_;
  ScriptCompiler::CompileOptions compile_options_;

  // The context of the caller for eval code, and the global context for a
  // global script. Will be a null handle otherwise.
  Handle<Context> context_;

  // Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
  Handle<FixedArray> feedback_vector_;

  // Compilation mode flag and whether deoptimization is allowed.
  Mode mode_;
  BailoutId osr_ast_id_;
  // The unoptimized code we patched for OSR may not be the shared code
  // afterwards, since we may need to compile it again to include deoptimization
  // data.  Keep track which code we patched.
  Handle<Code> unoptimized_code_;

  // Flag whether compilation needs to be aborted due to dependency change.
  bool abort_due_to_dependency_;

  // The zone from which the compilation pipeline working on this
  // CompilationInfo allocates.
  Zone* zone_;

  DeferredHandles* deferred_handles_;

  ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount];

  template<typename T>
  void SaveHandle(Handle<T> *object) {
    if (!object->is_null()) {
      Handle<T> handle(*(*object));
      *object = handle;
    }
  }

  BailoutReason bailout_reason_;

  int prologue_offset_;

  List<OffsetRange>* no_frame_ranges_;

  // A copy of shared_info()->opt_count() to avoid handle deref
  // during graph optimization.
  int opt_count_;

  // Number of parameters used for compilation of stubs that require arguments.
  int parameter_count_;

  bool this_has_uses_;

  Handle<Foreign> object_wrapper_;

  int optimization_id_;

  AstValueFactory* ast_value_factory_;
  bool ast_value_factory_owned_;

  DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};


// Exactly like a CompilationInfo, except also creates and enters a
// Zone on construction and deallocates it on exit.
class CompilationInfoWithZone: public CompilationInfo {
 public:
  explicit CompilationInfoWithZone(Handle<Script> script)
      : CompilationInfo(script, &zone_),
        zone_(script->GetIsolate()) {}
  explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)
      : CompilationInfo(shared_info, &zone_),
        zone_(shared_info->GetIsolate()) {}
  explicit CompilationInfoWithZone(Handle<JSFunction> closure)
      : CompilationInfo(closure, &zone_),
        zone_(closure->GetIsolate()) {}
  CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
      : CompilationInfo(stub, isolate, &zone_),
        zone_(isolate) {}

  // Virtual destructor because a CompilationInfoWithZone has to exit the
  // zone scope and get rid of dependent maps even when the destructor is
  // called when cast as a CompilationInfo.
  virtual ~CompilationInfoWithZone() {
    RollbackDependencies();
  }

 private:
  Zone zone_;
};


// A wrapper around a CompilationInfo that detaches the Handles from
// the underlying DeferredHandleScope and stores them in info_ on
// destruction.
class CompilationHandleScope BASE_EMBEDDED {
 public:
  explicit CompilationHandleScope(CompilationInfo* info)
      : deferred_(info->isolate()), info_(info) {}
  ~CompilationHandleScope() {
    info_->set_deferred_handles(deferred_.Detach());
  }

 private:
  DeferredHandleScope deferred_;
  CompilationInfo* info_;
};


class HGraph;
class HOptimizedGraphBuilder;
class LChunk;

// A helper class that calls the three compilation phases in
// Crankshaft and keeps track of its state.  The three phases
// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
// fail, bail-out to the full code generator or succeed.  Apart from
// their return value, the status of the phase last run can be checked
// using last_status().
class OptimizedCompileJob: public ZoneObject {
 public:
  explicit OptimizedCompileJob(CompilationInfo* info)
      : info_(info),
        graph_builder_(NULL),
        graph_(NULL),
        chunk_(NULL),
        last_status_(FAILED),
        awaiting_install_(false) { }

  enum Status {
    FAILED, BAILED_OUT, SUCCEEDED
  };

  MUST_USE_RESULT Status CreateGraph();
  MUST_USE_RESULT Status OptimizeGraph();
  MUST_USE_RESULT Status GenerateCode();

  Status last_status() const { return last_status_; }
  CompilationInfo* info() const { return info_; }
  Isolate* isolate() const { return info()->isolate(); }

  MUST_USE_RESULT Status AbortOptimization(
      BailoutReason reason = kNoReason) {
    if (reason != kNoReason) info_->set_bailout_reason(reason);
    return SetLastStatus(BAILED_OUT);
  }

  MUST_USE_RESULT Status AbortAndDisableOptimization(
      BailoutReason reason = kNoReason) {
    if (reason != kNoReason) info_->set_bailout_reason(reason);
    // Reference to shared function info does not change between phases.
    AllowDeferredHandleDereference allow_handle_dereference;
    info_->shared_info()->DisableOptimization(info_->bailout_reason());
    return SetLastStatus(BAILED_OUT);
  }

  void WaitForInstall() {
    DCHECK(info_->is_osr());
    awaiting_install_ = true;
  }

  bool IsWaitingForInstall() { return awaiting_install_; }

 private:
  CompilationInfo* info_;
  HOptimizedGraphBuilder* graph_builder_;
  HGraph* graph_;
  LChunk* chunk_;
  base::TimeDelta time_taken_to_create_graph_;
  base::TimeDelta time_taken_to_optimize_;
  base::TimeDelta time_taken_to_codegen_;
  Status last_status_;
  bool awaiting_install_;

  MUST_USE_RESULT Status SetLastStatus(Status status) {
    last_status_ = status;
    return last_status_;
  }
  void RecordOptimizationStats();

  struct Timer {
    Timer(OptimizedCompileJob* job, base::TimeDelta* location)
        : job_(job), location_(location) {
      DCHECK(location_ != NULL);
      timer_.Start();
    }

    ~Timer() {
      *location_ += timer_.Elapsed();
    }

    OptimizedCompileJob* job_;
    base::ElapsedTimer timer_;
    base::TimeDelta* location_;
  };
};


// The V8 compiler
//
// General strategy: Source code is translated into an anonymous function w/o
// parameters which then can be executed. If the source code contains other
// functions, they will be compiled and allocated as part of the compilation
// of the source code.

// Please note this interface returns shared function infos.  This means you
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
// real function with a context.

class Compiler : public AllStatic {
 public:
  MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
      Handle<JSFunction> function);
  MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
      Handle<SharedFunctionInfo> shared);
  static bool EnsureCompiled(Handle<JSFunction> function,
                             ClearExceptionFlag flag);
  MUST_USE_RESULT static MaybeHandle<Code> GetCodeForDebugging(
      Handle<JSFunction> function);

  static void CompileForLiveEdit(Handle<Script> script);

  // Compile a String source within a context for eval.
  MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
      Handle<String> source,
      Handle<Context> context,
      StrictMode strict_mode,
      ParseRestriction restriction,
      int scope_position);

  // Compile a String source within a context.
  static Handle<SharedFunctionInfo> CompileScript(
      Handle<String> source, Handle<Object> script_name, int line_offset,
      int column_offset, bool is_shared_cross_origin, Handle<Context> context,
      v8::Extension* extension, ScriptData** cached_data,
      ScriptCompiler::CompileOptions compile_options,
      NativesFlag is_natives_code);

  // Create a shared function info object (the code may be lazily compiled).
  static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
                                                      Handle<Script> script,
                                                      CompilationInfo* outer);

  enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };

  // Generate and return optimized code or start a concurrent optimization job.
  // In the latter case, return the InOptimizationQueue builtin.  On failure,
  // return the empty handle.
  MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
      Handle<JSFunction> function,
      Handle<Code> current_code,
      ConcurrencyMode mode,
      BailoutId osr_ast_id = BailoutId::None());

  // Generate and return code from previously queued optimization job.
  // On failure, return the empty handle.
  static Handle<Code> GetConcurrentlyOptimizedCode(OptimizedCompileJob* job);

  static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
                                        CompilationInfo* info,
                                        Handle<SharedFunctionInfo> shared);
};


class CompilationPhase BASE_EMBEDDED {
 public:
  CompilationPhase(const char* name, CompilationInfo* info);
  ~CompilationPhase();

 protected:
  bool ShouldProduceTraceOutput() const;

  const char* name() const { return name_; }
  CompilationInfo* info() const { return info_; }
  Isolate* isolate() const { return info()->isolate(); }
  Zone* zone() { return &zone_; }

 private:
  const char* name_;
  CompilationInfo* info_;
  Zone zone_;
  unsigned info_zone_start_allocation_size_;
  base::ElapsedTimer timer_;

  DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
};

} }  // namespace v8::internal

#endif  // V8_COMPILER_H_
