<commit_before>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_STACK_H_
#define ART_RUNTIME_STACK_H_

#include "dex_file.h"
#include "instrumentation.h"
#include "base/macros.h"
#include "arch/context.h"

#include <stdint.h>
#include <string>

namespace art {

namespace mirror {
  class ArtMethod;
  class Object;
}  // namespace mirror

class Context;
class ShadowFrame;
class StackIndirectReferenceTable;
class ScopedObjectAccess;
class Thread;

// The kind of vreg being accessed in calls to Set/GetVReg.
enum VRegKind {
  kReferenceVReg,
  kIntVReg,
  kFloatVReg,
  kLongLoVReg,
  kLongHiVReg,
  kDoubleLoVReg,
  kDoubleHiVReg,
  kConstant,
  kImpreciseConstant,
  kUndefined,
};

// ShadowFrame has 3 possible layouts:
//  - portable - a unified array of VRegs and references. Precise references need GC maps.
//  - interpreter - separate VRegs and reference arrays. References are in the reference array.
//  - JNI - just VRegs, but where every VReg holds a reference.
class ShadowFrame {
 public:
  // Compute size of ShadowFrame in bytes.
  static size_t ComputeSize(uint32_t num_vregs) {
    return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) +
           (sizeof(mirror::Object*) * num_vregs);
  }

  // Create ShadowFrame in heap for deoptimization.
  static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
                             mirror::ArtMethod* method, uint32_t dex_pc) {
    uint8_t* memory = new uint8_t[ComputeSize(num_vregs)];
    ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
    return sf;
  }

  // Create ShadowFrame for interpreter using provided memory.
  static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
                             mirror::ArtMethod* method, uint32_t dex_pc, void* memory) {
    ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
    return sf;
  }
  ~ShadowFrame() {}

  bool HasReferenceArray() const {
#if defined(ART_USE_PORTABLE_COMPILER)
    return (number_of_vregs_ & kHasReferenceArray) != 0;
#else
    return true;
#endif
  }

  uint32_t NumberOfVRegs() const {
#if defined(ART_USE_PORTABLE_COMPILER)
    return number_of_vregs_ & ~kHasReferenceArray;
#else
    return number_of_vregs_;
#endif
  }

  void SetNumberOfVRegs(uint32_t number_of_vregs) {
#if defined(ART_USE_PORTABLE_COMPILER)
    number_of_vregs_ = number_of_vregs | (number_of_vregs_ & kHasReferenceArray);
#else
    UNUSED(number_of_vregs);
    UNIMPLEMENTED(FATAL) << "Should only be called when portable is enabled";
#endif
  }

  uint32_t GetDexPC() const {
    return dex_pc_;
  }

  void SetDexPC(uint32_t dex_pc) {
    dex_pc_ = dex_pc;
  }

  ShadowFrame* GetLink() const {
    return link_;
  }

  void SetLink(ShadowFrame* frame) {
    DCHECK_NE(this, frame);
    link_ = frame;
  }

  int32_t GetVReg(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    const uint32_t* vreg = &vregs_[i];
    return *reinterpret_cast<const int32_t*>(vreg);
  }

  float GetVRegFloat(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    // NOTE: Strict-aliasing?
    const uint32_t* vreg = &vregs_[i];
    return *reinterpret_cast<const float*>(vreg);
  }

  int64_t GetVRegLong(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    const uint32_t* vreg = &vregs_[i];
    return *reinterpret_cast<const int64_t*>(vreg);
  }

  double GetVRegDouble(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    const uint32_t* vreg = &vregs_[i];
    return *reinterpret_cast<const double*>(vreg);
  }

  mirror::Object* GetVRegReference(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    if (HasReferenceArray()) {
      mirror::Object* ref = References()[i];
      // If the vreg reference is not equal to the vreg then the vreg reference is stale.
      if (reinterpret_cast<uint32_t>(ref) != vregs_[i]) {
        return nullptr;
      }
      return ref;
    } else {
      const uint32_t* vreg = &vregs_[i];
      return *reinterpret_cast<mirror::Object* const*>(vreg);
    }
  }

  // Get view of vregs as range of consecutive arguments starting at i.
  uint32_t* GetVRegArgs(size_t i) {
    return &vregs_[i];
  }

  void SetVReg(size_t i, int32_t val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<int32_t*>(vreg) = val;
  }

  void SetVRegFloat(size_t i, float val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<float*>(vreg) = val;
  }

  void SetVRegLong(size_t i, int64_t val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<int64_t*>(vreg) = val;
  }

  void SetVRegDouble(size_t i, double val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<double*>(vreg) = val;
  }

  void SetVRegReference(size_t i, mirror::Object* val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<mirror::Object**>(vreg) = val;
    if (HasReferenceArray()) {
      References()[i] = val;
    }
  }

  mirror::ArtMethod* GetMethod() const {
    DCHECK_NE(method_, static_cast<void*>(NULL));
    return method_;
  }

  mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  ThrowLocation GetCurrentLocationForThrow() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void SetMethod(mirror::ArtMethod* method) {
#if defined(ART_USE_PORTABLE_COMPILER)
    DCHECK_NE(method, static_cast<void*>(NULL));
    method_ = method;
#else
    UNUSED(method);
    UNIMPLEMENTED(FATAL) << "Should only be called when portable is enabled";<commit_msg>am e47637cc: 4-byte align 64-bit values in Get/Set Double/Long for GCC 4.8.<commit_after>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_STACK_H_
#define ART_RUNTIME_STACK_H_

#include "dex_file.h"
#include "instrumentation.h"
#include "base/macros.h"
#include "arch/context.h"

#include <stdint.h>
#include <string>

namespace art {

namespace mirror {
  class ArtMethod;
  class Object;
}  // namespace mirror

class Context;
class ShadowFrame;
class StackIndirectReferenceTable;
class ScopedObjectAccess;
class Thread;

// The kind of vreg being accessed in calls to Set/GetVReg.
enum VRegKind {
  kReferenceVReg,
  kIntVReg,
  kFloatVReg,
  kLongLoVReg,
  kLongHiVReg,
  kDoubleLoVReg,
  kDoubleHiVReg,
  kConstant,
  kImpreciseConstant,
  kUndefined,
};

// ShadowFrame has 3 possible layouts:
//  - portable - a unified array of VRegs and references. Precise references need GC maps.
//  - interpreter - separate VRegs and reference arrays. References are in the reference array.
//  - JNI - just VRegs, but where every VReg holds a reference.
class ShadowFrame {
 public:
  // Compute size of ShadowFrame in bytes.
  static size_t ComputeSize(uint32_t num_vregs) {
    return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) +
           (sizeof(mirror::Object*) * num_vregs);
  }

  // Create ShadowFrame in heap for deoptimization.
  static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
                             mirror::ArtMethod* method, uint32_t dex_pc) {
    uint8_t* memory = new uint8_t[ComputeSize(num_vregs)];
    ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
    return sf;
  }

  // Create ShadowFrame for interpreter using provided memory.
  static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
                             mirror::ArtMethod* method, uint32_t dex_pc, void* memory) {
    ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
    return sf;
  }
  ~ShadowFrame() {}

  bool HasReferenceArray() const {
#if defined(ART_USE_PORTABLE_COMPILER)
    return (number_of_vregs_ & kHasReferenceArray) != 0;
#else
    return true;
#endif
  }

  uint32_t NumberOfVRegs() const {
#if defined(ART_USE_PORTABLE_COMPILER)
    return number_of_vregs_ & ~kHasReferenceArray;
#else
    return number_of_vregs_;
#endif
  }

  void SetNumberOfVRegs(uint32_t number_of_vregs) {
#if defined(ART_USE_PORTABLE_COMPILER)
    number_of_vregs_ = number_of_vregs | (number_of_vregs_ & kHasReferenceArray);
#else
    UNUSED(number_of_vregs);
    UNIMPLEMENTED(FATAL) << "Should only be called when portable is enabled";
#endif
  }

  uint32_t GetDexPC() const {
    return dex_pc_;
  }

  void SetDexPC(uint32_t dex_pc) {
    dex_pc_ = dex_pc;
  }

  ShadowFrame* GetLink() const {
    return link_;
  }

  void SetLink(ShadowFrame* frame) {
    DCHECK_NE(this, frame);
    link_ = frame;
  }

  int32_t GetVReg(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    const uint32_t* vreg = &vregs_[i];
    return *reinterpret_cast<const int32_t*>(vreg);
  }

  float GetVRegFloat(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    // NOTE: Strict-aliasing?
    const uint32_t* vreg = &vregs_[i];
    return *reinterpret_cast<const float*>(vreg);
  }

  int64_t GetVRegLong(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    const uint32_t* vreg = &vregs_[i];
    // Alignment attribute required for GCC 4.8
    typedef const int64_t unaligned_int64 __attribute__ ((aligned (4)));
    return *reinterpret_cast<unaligned_int64*>(vreg);
  }

  double GetVRegDouble(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    const uint32_t* vreg = &vregs_[i];
    // Alignment attribute required for GCC 4.8
    typedef const double unaligned_double __attribute__ ((aligned (4)));
    return *reinterpret_cast<unaligned_double*>(vreg);
  }

  mirror::Object* GetVRegReference(size_t i) const {
    DCHECK_LT(i, NumberOfVRegs());
    if (HasReferenceArray()) {
      mirror::Object* ref = References()[i];
      // If the vreg reference is not equal to the vreg then the vreg reference is stale.
      if (reinterpret_cast<uint32_t>(ref) != vregs_[i]) {
        return nullptr;
      }
      return ref;
    } else {
      const uint32_t* vreg = &vregs_[i];
      return *reinterpret_cast<mirror::Object* const*>(vreg);
    }
  }

  // Get view of vregs as range of consecutive arguments starting at i.
  uint32_t* GetVRegArgs(size_t i) {
    return &vregs_[i];
  }

  void SetVReg(size_t i, int32_t val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<int32_t*>(vreg) = val;
  }

  void SetVRegFloat(size_t i, float val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<float*>(vreg) = val;
  }

  void SetVRegLong(size_t i, int64_t val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    // Alignment attribute required for GCC 4.8
    typedef int64_t unaligned_int64 __attribute__ ((aligned (4)));
    *reinterpret_cast<unaligned_int64*>(vreg) = val;
  }

  void SetVRegDouble(size_t i, double val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    // Alignment attribute required for GCC 4.8
    typedef double unaligned_double __attribute__ ((aligned (4)));
    *reinterpret_cast<unaligned_double*>(vreg) = val;
  }

  void SetVRegReference(size_t i, mirror::Object* val) {
    DCHECK_LT(i, NumberOfVRegs());
    uint32_t* vreg = &vregs_[i];
    *reinterpret_cast<mirror::Object**>(vreg) = val;
    if (HasReferenceArray()) {
      References()[i] = val;
    }
  }

  mirror::ArtMethod* GetMethod() const {
    DCHECK_NE(method_, static_cast<void*>(NULL));
    return method_;
  }

  mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  ThrowLocation GetCurrentLocationForThrow() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void SetMethod(mirror::ArtMethod* method) {
#if defined(ART_USE_PORTABLE_COMPILER)
    DCHECK_NE(method, static_cast<void*>(NULL));
    method_ = method;
#else
    UNUSED(method);
    UNIMPLEMENTED(FATAL) << "Should only be called when portable is enabled";
{'fraction_non_alphanumeric': 0.10825367925959642, 'fraction_numerical': 0.013503262023972083, 'mean_word_length': 3.8934669636228656, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1496004', 'n_tokens_mistral': 4698, 'n_tokens_neox': 4557, 'n_words': 1160}