LCOV - code coverage report
Current view: top level - js/src/wasm - WasmTypes.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 297 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 57 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  *
       4             :  * Copyright 2015 Mozilla Foundation
       5             :  *
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  */
      18             : 
      19             : #include "wasm/WasmTypes.h"
      20             : 
      21             : #include "wasm/WasmBaselineCompile.h"
      22             : #include "wasm/WasmInstance.h"
      23             : #include "wasm/WasmSerialize.h"
      24             : 
      25             : #include "jsobjinlines.h"
      26             : 
      27             : using namespace js;
      28             : using namespace js::jit;
      29             : using namespace js::wasm;
      30             : 
      31             : using mozilla::IsPowerOfTwo;
      32             : 
      33             : void
      34           0 : Val::writePayload(uint8_t* dst) const
      35             : {
      36           0 :     switch (type_) {
      37             :       case ValType::I32:
      38             :       case ValType::F32:
      39           0 :         memcpy(dst, &u.i32_, sizeof(u.i32_));
      40           0 :         return;
      41             :       case ValType::I64:
      42             :       case ValType::F64:
      43           0 :         memcpy(dst, &u.i64_, sizeof(u.i64_));
      44           0 :         return;
      45             :       case ValType::I8x16:
      46             :       case ValType::I16x8:
      47             :       case ValType::I32x4:
      48             :       case ValType::F32x4:
      49             :       case ValType::B8x16:
      50             :       case ValType::B16x8:
      51             :       case ValType::B32x4:
      52           0 :         memcpy(dst, &u, jit::Simd128DataSize);
      53           0 :         return;
      54             :     }
      55             : }
      56             : 
      57             : bool
      58           0 : wasm::IsRoundingFunction(SymbolicAddress callee, jit::RoundingMode* mode)
      59             : {
      60           0 :     switch (callee) {
      61             :       case SymbolicAddress::FloorD:
      62             :       case SymbolicAddress::FloorF:
      63           0 :         *mode = jit::RoundingMode::Down;
      64           0 :         return true;
      65             :       case SymbolicAddress::CeilD:
      66             :       case SymbolicAddress::CeilF:
      67           0 :         *mode = jit::RoundingMode::Up;
      68           0 :         return true;
      69             :       case SymbolicAddress::TruncD:
      70             :       case SymbolicAddress::TruncF:
      71           0 :         *mode = jit::RoundingMode::TowardsZero;
      72           0 :         return true;
      73             :       case SymbolicAddress::NearbyIntD:
      74             :       case SymbolicAddress::NearbyIntF:
      75           0 :         *mode = jit::RoundingMode::NearestTiesToEven;
      76           0 :         return true;
      77             :       default:
      78           0 :         return false;
      79             :     }
      80             : }
      81             : 
      82             : static uint32_t
      83           0 : GetCPUID()
      84             : {
      85             :     enum Arch {
      86             :         X86 = 0x1,
      87             :         X64 = 0x2,
      88             :         ARM = 0x3,
      89             :         MIPS = 0x4,
      90             :         MIPS64 = 0x5,
      91             :         ARCH_BITS = 3
      92             :     };
      93             : 
      94             : #if defined(JS_CODEGEN_X86)
      95             :     MOZ_ASSERT(uint32_t(jit::CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS));
      96             :     return X86 | (uint32_t(jit::CPUInfo::GetSSEVersion()) << ARCH_BITS);
      97             : #elif defined(JS_CODEGEN_X64)
      98           0 :     MOZ_ASSERT(uint32_t(jit::CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS));
      99           0 :     return X64 | (uint32_t(jit::CPUInfo::GetSSEVersion()) << ARCH_BITS);
     100             : #elif defined(JS_CODEGEN_ARM)
     101             :     MOZ_ASSERT(jit::GetARMFlags() <= (UINT32_MAX >> ARCH_BITS));
     102             :     return ARM | (jit::GetARMFlags() << ARCH_BITS);
     103             : #elif defined(JS_CODEGEN_ARM64)
     104             :     MOZ_CRASH("not enabled");
     105             : #elif defined(JS_CODEGEN_MIPS32)
     106             :     MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
     107             :     return MIPS | (jit::GetMIPSFlags() << ARCH_BITS);
     108             : #elif defined(JS_CODEGEN_MIPS64)
     109             :     MOZ_ASSERT(jit::GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS));
     110             :     return MIPS64 | (jit::GetMIPSFlags() << ARCH_BITS);
     111             : #elif defined(JS_CODEGEN_NONE)
     112             :     return 0;
     113             : #else
     114             : # error "unknown architecture"
     115             : #endif
     116             : }
     117             : 
     118             : size_t
     119           0 : Sig::serializedSize() const
     120             : {
     121             :     return sizeof(ret_) +
     122           0 :            SerializedPodVectorSize(args_);
     123             : }
     124             : 
     125             : uint8_t*
     126           0 : Sig::serialize(uint8_t* cursor) const
     127             : {
     128           0 :     cursor = WriteScalar<ExprType>(cursor, ret_);
     129           0 :     cursor = SerializePodVector(cursor, args_);
     130           0 :     return cursor;
     131             : }
     132             : 
     133             : const uint8_t*
     134           0 : Sig::deserialize(const uint8_t* cursor)
     135             : {
     136           0 :     (cursor = ReadScalar<ExprType>(cursor, &ret_)) &&
     137           0 :     (cursor = DeserializePodVector(cursor, &args_));
     138           0 :     return cursor;
     139             : }
     140             : 
     141             : size_t
     142           0 : Sig::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
     143             : {
     144           0 :     return args_.sizeOfExcludingThis(mallocSizeOf);
     145             : }
     146             : 
     147             : typedef uint32_t ImmediateType;  // for 32/64 consistency
     148             : static const unsigned sTotalBits = sizeof(ImmediateType) * 8;
     149             : static const unsigned sTagBits = 1;
     150             : static const unsigned sReturnBit = 1;
     151             : static const unsigned sLengthBits = 4;
     152             : static const unsigned sTypeBits = 2;
     153             : static const unsigned sMaxTypes = (sTotalBits - sTagBits - sReturnBit - sLengthBits) / sTypeBits;
     154             : 
     155             : static bool
     156           0 : IsImmediateType(ValType vt)
     157             : {
     158           0 :     switch (vt) {
     159             :       case ValType::I32:
     160             :       case ValType::I64:
     161             :       case ValType::F32:
     162             :       case ValType::F64:
     163           0 :         return true;
     164             :       case ValType::I8x16:
     165             :       case ValType::I16x8:
     166             :       case ValType::I32x4:
     167             :       case ValType::F32x4:
     168             :       case ValType::B8x16:
     169             :       case ValType::B16x8:
     170             :       case ValType::B32x4:
     171           0 :         return false;
     172             :     }
     173           0 :     MOZ_CRASH("bad ValType");
     174             : }
     175             : 
     176             : static unsigned
     177           0 : EncodeImmediateType(ValType vt)
     178             : {
     179             :     static_assert(3 < (1 << sTypeBits), "fits");
     180           0 :     switch (vt) {
     181             :       case ValType::I32:
     182           0 :         return 0;
     183             :       case ValType::I64:
     184           0 :         return 1;
     185             :       case ValType::F32:
     186           0 :         return 2;
     187             :       case ValType::F64:
     188           0 :         return 3;
     189             :       case ValType::I8x16:
     190             :       case ValType::I16x8:
     191             :       case ValType::I32x4:
     192             :       case ValType::F32x4:
     193             :       case ValType::B8x16:
     194             :       case ValType::B16x8:
     195             :       case ValType::B32x4:
     196           0 :         break;
     197             :     }
     198           0 :     MOZ_CRASH("bad ValType");
     199             : }
     200             : 
     201             : /* static */ bool
     202           0 : SigIdDesc::isGlobal(const Sig& sig)
     203             : {
     204           0 :     unsigned numTypes = (sig.ret() == ExprType::Void ? 0 : 1) +
     205           0 :                         (sig.args().length());
     206           0 :     if (numTypes > sMaxTypes)
     207           0 :         return true;
     208             : 
     209           0 :     if (sig.ret() != ExprType::Void && !IsImmediateType(NonVoidToValType(sig.ret())))
     210           0 :         return true;
     211             : 
     212           0 :     for (ValType v : sig.args()) {
     213           0 :         if (!IsImmediateType(v))
     214           0 :             return true;
     215             :     }
     216             : 
     217           0 :     return false;
     218             : }
     219             : 
     220             : /* static */ SigIdDesc
     221           0 : SigIdDesc::global(const Sig& sig, uint32_t globalDataOffset)
     222             : {
     223           0 :     MOZ_ASSERT(isGlobal(sig));
     224           0 :     return SigIdDesc(Kind::Global, globalDataOffset);
     225             : }
     226             : 
     227             : static ImmediateType
     228           0 : LengthToBits(uint32_t length)
     229             : {
     230             :     static_assert(sMaxTypes <= ((1 << sLengthBits) - 1), "fits");
     231           0 :     MOZ_ASSERT(length <= sMaxTypes);
     232           0 :     return length;
     233             : }
     234             : 
     235             : /* static */ SigIdDesc
     236           0 : SigIdDesc::immediate(const Sig& sig)
     237             : {
     238           0 :     ImmediateType immediate = ImmediateBit;
     239           0 :     uint32_t shift = sTagBits;
     240             : 
     241           0 :     if (sig.ret() != ExprType::Void) {
     242           0 :         immediate |= (1 << shift);
     243           0 :         shift += sReturnBit;
     244             : 
     245           0 :         immediate |= EncodeImmediateType(NonVoidToValType(sig.ret())) << shift;
     246           0 :         shift += sTypeBits;
     247             :     } else {
     248           0 :         shift += sReturnBit;
     249             :     }
     250             : 
     251           0 :     immediate |= LengthToBits(sig.args().length()) << shift;
     252           0 :     shift += sLengthBits;
     253             : 
     254           0 :     for (ValType argType : sig.args()) {
     255           0 :         immediate |= EncodeImmediateType(argType) << shift;
     256           0 :         shift += sTypeBits;
     257             :     }
     258             : 
     259           0 :     MOZ_ASSERT(shift <= sTotalBits);
     260           0 :     return SigIdDesc(Kind::Immediate, immediate);
     261             : }
     262             : 
     263             : size_t
     264           0 : SigWithId::serializedSize() const
     265             : {
     266           0 :     return Sig::serializedSize() +
     267           0 :            sizeof(id);
     268             : }
     269             : 
     270             : uint8_t*
     271           0 : SigWithId::serialize(uint8_t* cursor) const
     272             : {
     273           0 :     cursor = Sig::serialize(cursor);
     274           0 :     cursor = WriteBytes(cursor, &id, sizeof(id));
     275           0 :     return cursor;
     276             : }
     277             : 
     278             : const uint8_t*
     279           0 : SigWithId::deserialize(const uint8_t* cursor)
     280             : {
     281           0 :     (cursor = Sig::deserialize(cursor)) &&
     282           0 :     (cursor = ReadBytes(cursor, &id, sizeof(id)));
     283           0 :     return cursor;
     284             : }
     285             : 
     286             : size_t
     287           0 : SigWithId::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
     288             : {
     289           0 :     return Sig::sizeOfExcludingThis(mallocSizeOf);
     290             : }
     291             : 
     292             : size_t
     293           0 : Import::serializedSize() const
     294             : {
     295           0 :     return module.serializedSize() +
     296           0 :            field.serializedSize() +
     297           0 :            sizeof(kind);
     298             : }
     299             : 
     300             : uint8_t*
     301           0 : Import::serialize(uint8_t* cursor) const
     302             : {
     303           0 :     cursor = module.serialize(cursor);
     304           0 :     cursor = field.serialize(cursor);
     305           0 :     cursor = WriteScalar<DefinitionKind>(cursor, kind);
     306           0 :     return cursor;
     307             : }
     308             : 
     309             : const uint8_t*
     310           0 : Import::deserialize(const uint8_t* cursor)
     311             : {
     312           0 :     (cursor = module.deserialize(cursor)) &&
     313           0 :     (cursor = field.deserialize(cursor)) &&
     314           0 :     (cursor = ReadScalar<DefinitionKind>(cursor, &kind));
     315           0 :     return cursor;
     316             : }
     317             : 
     318             : size_t
     319           0 : Import::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
     320             : {
     321           0 :     return module.sizeOfExcludingThis(mallocSizeOf) +
     322           0 :            field.sizeOfExcludingThis(mallocSizeOf);
     323             : }
     324             : 
     325           0 : Export::Export(UniqueChars fieldName, uint32_t index, DefinitionKind kind)
     326           0 :   : fieldName_(Move(fieldName))
     327             : {
     328           0 :     pod.kind_ = kind;
     329           0 :     pod.index_ = index;
     330           0 : }
     331             : 
     332           0 : Export::Export(UniqueChars fieldName, DefinitionKind kind)
     333           0 :   : fieldName_(Move(fieldName))
     334             : {
     335           0 :     pod.kind_ = kind;
     336           0 :     pod.index_ = 0;
     337           0 : }
     338             : 
     339             : uint32_t
     340           0 : Export::funcIndex() const
     341             : {
     342           0 :     MOZ_ASSERT(pod.kind_ == DefinitionKind::Function);
     343           0 :     return pod.index_;
     344             : }
     345             : 
     346             : uint32_t
     347           0 : Export::globalIndex() const
     348             : {
     349           0 :     MOZ_ASSERT(pod.kind_ == DefinitionKind::Global);
     350           0 :     return pod.index_;
     351             : }
     352             : 
     353             : size_t
     354           0 : Export::serializedSize() const
     355             : {
     356           0 :     return fieldName_.serializedSize() +
     357           0 :            sizeof(pod);
     358             : }
     359             : 
     360             : uint8_t*
     361           0 : Export::serialize(uint8_t* cursor) const
     362             : {
     363           0 :     cursor = fieldName_.serialize(cursor);
     364           0 :     cursor = WriteBytes(cursor, &pod, sizeof(pod));
     365           0 :     return cursor;
     366             : }
     367             : 
     368             : const uint8_t*
     369           0 : Export::deserialize(const uint8_t* cursor)
     370             : {
     371           0 :     (cursor = fieldName_.deserialize(cursor)) &&
     372           0 :     (cursor = ReadBytes(cursor, &pod, sizeof(pod)));
     373           0 :     return cursor;
     374             : }
     375             : 
     376             : size_t
     377           0 : Export::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
     378             : {
     379           0 :     return fieldName_.sizeOfExcludingThis(mallocSizeOf);
     380             : }
     381             : 
     382             : size_t
     383           0 : ElemSegment::serializedSize() const
     384             : {
     385             :     return sizeof(tableIndex) +
     386             :            sizeof(offset) +
     387           0 :            SerializedPodVectorSize(elemFuncIndices) +
     388           0 :            SerializedPodVectorSize(elemCodeRangeIndices);
     389             : }
     390             : 
     391             : uint8_t*
     392           0 : ElemSegment::serialize(uint8_t* cursor) const
     393             : {
     394           0 :     cursor = WriteBytes(cursor, &tableIndex, sizeof(tableIndex));
     395           0 :     cursor = WriteBytes(cursor, &offset, sizeof(offset));
     396           0 :     cursor = SerializePodVector(cursor, elemFuncIndices);
     397           0 :     cursor = SerializePodVector(cursor, elemCodeRangeIndices);
     398           0 :     return cursor;
     399             : }
     400             : 
     401             : const uint8_t*
     402           0 : ElemSegment::deserialize(const uint8_t* cursor)
     403             : {
     404           0 :     (cursor = ReadBytes(cursor, &tableIndex, sizeof(tableIndex))) &&
     405           0 :     (cursor = ReadBytes(cursor, &offset, sizeof(offset))) &&
     406           0 :     (cursor = DeserializePodVector(cursor, &elemFuncIndices)) &&
     407           0 :     (cursor = DeserializePodVector(cursor, &elemCodeRangeIndices));
     408           0 :     return cursor;
     409             : }
     410             : 
     411             : size_t
     412           0 : ElemSegment::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
     413             : {
     414           0 :     return elemFuncIndices.sizeOfExcludingThis(mallocSizeOf) +
     415           0 :            elemCodeRangeIndices.sizeOfExcludingThis(mallocSizeOf);
     416             : }
     417             : 
     418           0 : Assumptions::Assumptions(JS::BuildIdCharVector&& buildId)
     419           0 :   : cpuId(GetCPUID()),
     420           0 :     buildId(Move(buildId))
     421           0 : {}
     422             : 
     423           0 : Assumptions::Assumptions()
     424           0 :   : cpuId(GetCPUID()),
     425           0 :     buildId()
     426           0 : {}
     427             : 
     428             : bool
     429           0 : Assumptions::initBuildIdFromContext(JSContext* cx)
     430             : {
     431           0 :     if (!cx->buildIdOp() || !cx->buildIdOp()(&buildId)) {
     432           0 :         ReportOutOfMemory(cx);
     433           0 :         return false;
     434             :     }
     435           0 :     return true;
     436             : }
     437             : 
     438             : bool
     439           0 : Assumptions::clone(const Assumptions& other)
     440             : {
     441           0 :     cpuId = other.cpuId;
     442           0 :     return buildId.appendAll(other.buildId);
     443             : }
     444             : 
     445             : bool
     446           0 : Assumptions::operator==(const Assumptions& rhs) const
     447             : {
     448           0 :     return cpuId == rhs.cpuId &&
     449           0 :            buildId.length() == rhs.buildId.length() &&
     450           0 :            PodEqual(buildId.begin(), rhs.buildId.begin(), buildId.length());
     451             : }
     452             : 
     453             : size_t
     454           0 : Assumptions::serializedSize() const
     455             : {
     456             :     return sizeof(uint32_t) +
     457           0 :            SerializedPodVectorSize(buildId);
     458             : }
     459             : 
     460             : uint8_t*
     461           0 : Assumptions::serialize(uint8_t* cursor) const
     462             : {
     463             :     // The format of serialized Assumptions must never change in a way that
     464             :     // would cause old cache files written with by an old build-id to match the
     465             :     // assumptions of a different build-id.
     466             : 
     467           0 :     cursor = WriteScalar<uint32_t>(cursor, cpuId);
     468           0 :     cursor = SerializePodVector(cursor, buildId);
     469           0 :     return cursor;
     470             : }
     471             : 
     472             : const uint8_t*
     473           0 : Assumptions::deserialize(const uint8_t* cursor, size_t remain)
     474             : {
     475           0 :     (cursor = ReadScalarChecked<uint32_t>(cursor, &remain, &cpuId)) &&
     476           0 :     (cursor = DeserializePodVectorChecked(cursor, &remain, &buildId));
     477           0 :     return cursor;
     478             : }
     479             : 
     480             : size_t
     481           0 : Assumptions::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
     482             : {
     483           0 :     return buildId.sizeOfExcludingThis(mallocSizeOf);
     484             : }
     485             : 
     486             : //  Heap length on ARM should fit in an ARM immediate. We approximate the set
     487             : //  of valid ARM immediates with the predicate:
     488             : //    2^n for n in [16, 24)
     489             : //  or
     490             : //    2^24 * n for n >= 1.
     491             : bool
     492           0 : wasm::IsValidARMImmediate(uint32_t i)
     493             : {
     494           0 :     bool valid = (IsPowerOfTwo(i) ||
     495           0 :                   (i & 0x00ffffff) == 0);
     496             : 
     497           0 :     MOZ_ASSERT_IF(valid, i % PageSize == 0);
     498             : 
     499           0 :     return valid;
     500             : }
     501             : 
     502             : uint32_t
     503           0 : wasm::RoundUpToNextValidARMImmediate(uint32_t i)
     504             : {
     505           0 :     MOZ_ASSERT(i <= 0xff000000);
     506             : 
     507           0 :     if (i <= 16 * 1024 * 1024)
     508           0 :         i = i ? mozilla::RoundUpPow2(i) : 0;
     509             :     else
     510           0 :         i = (i + 0x00ffffff) & ~0x00ffffff;
     511             : 
     512           0 :     MOZ_ASSERT(IsValidARMImmediate(i));
     513             : 
     514           0 :     return i;
     515             : }
     516             : 
     517             : #ifndef WASM_HUGE_MEMORY
     518             : 
     519             : bool
     520             : wasm::IsValidBoundsCheckImmediate(uint32_t i)
     521             : {
     522             : #ifdef JS_CODEGEN_ARM
     523             :     return IsValidARMImmediate(i);
     524             : #else
     525             :     return true;
     526             : #endif
     527             : }
     528             : 
     529             : size_t
     530             : wasm::ComputeMappedSize(uint32_t maxSize)
     531             : {
     532             :     MOZ_ASSERT(maxSize % PageSize == 0);
     533             : 
     534             :     // It is the bounds-check limit, not the mapped size, that gets baked into
     535             :     // code. Thus round up the maxSize to the next valid immediate value
     536             :     // *before* adding in the guard page.
     537             : 
     538             : # ifdef JS_CODEGEN_ARM
     539             :     uint32_t boundsCheckLimit = RoundUpToNextValidARMImmediate(maxSize);
     540             : # else
     541             :     uint32_t boundsCheckLimit = maxSize;
     542             : # endif
     543             :     MOZ_ASSERT(IsValidBoundsCheckImmediate(boundsCheckLimit));
     544             : 
     545             :     MOZ_ASSERT(boundsCheckLimit % gc::SystemPageSize() == 0);
     546             :     MOZ_ASSERT(GuardSize % gc::SystemPageSize() == 0);
     547             :     return boundsCheckLimit + GuardSize;
     548             : }
     549             : 
     550             : #endif  // WASM_HUGE_MEMORY
     551             : 
     552             : void
     553           0 : DebugFrame::alignmentStaticAsserts()
     554             : {
     555             :     // VS2017 doesn't consider offsetOfFrame() to be a constexpr, so we have
     556             :     // to use offsetof directly. These asserts can't be at class-level
     557             :     // because the type is incomplete.
     558             : 
     559             :     static_assert(WasmStackAlignment >= Alignment,
     560             :                   "Aligned by ABI before pushing DebugFrame");
     561             :     static_assert((offsetof(DebugFrame, frame_) + sizeof(Frame)) % Alignment == 0,
     562             :                   "Aligned after pushing DebugFrame");
     563           0 : }
     564             : 
     565             : GlobalObject*
     566           0 : DebugFrame::global() const
     567             : {
     568           0 :     return &instance()->object()->global();
     569             : }
     570             : 
     571             : JSObject*
     572           0 : DebugFrame::environmentChain() const
     573             : {
     574           0 :     return &global()->lexicalEnvironment();
     575             : }
     576             : 
     577             : bool
     578           0 : DebugFrame::getLocal(uint32_t localIndex, MutableHandleValue vp)
     579             : {
     580           0 :     ValTypeVector locals;
     581             :     size_t argsLength;
     582           0 :     if (!instance()->debug().debugGetLocalTypes(funcIndex(), &locals, &argsLength))
     583           0 :         return false;
     584             : 
     585           0 :     BaseLocalIter iter(locals, argsLength, /* debugEnabled = */ true);
     586           0 :     while (!iter.done() && iter.index() < localIndex)
     587           0 :         iter++;
     588           0 :     MOZ_ALWAYS_TRUE(!iter.done());
     589             : 
     590           0 :     uint8_t* frame = static_cast<uint8_t*>((void*)this) + offsetOfFrame();
     591           0 :     void* dataPtr = frame - iter.frameOffset();
     592           0 :     switch (iter.mirType()) {
     593             :       case jit::MIRType::Int32:
     594           0 :           vp.set(Int32Value(*static_cast<int32_t*>(dataPtr)));
     595           0 :           break;
     596             :       case jit::MIRType::Int64:
     597             :           // Just display as a Number; it's ok if we lose some precision
     598           0 :           vp.set(NumberValue((double)*static_cast<int64_t*>(dataPtr)));
     599           0 :           break;
     600             :       case jit::MIRType::Float32:
     601           0 :           vp.set(NumberValue(JS::CanonicalizeNaN(*static_cast<float*>(dataPtr))));
     602           0 :           break;
     603             :       case jit::MIRType::Double:
     604           0 :           vp.set(NumberValue(JS::CanonicalizeNaN(*static_cast<double*>(dataPtr))));
     605           0 :           break;
     606             :       default:
     607           0 :           MOZ_CRASH("local type");
     608             :     }
     609           0 :     return true;
     610             : }
     611             : 
     612             : void
     613           0 : DebugFrame::updateReturnJSValue()
     614             : {
     615           0 :     hasCachedReturnJSValue_ = true;
     616           0 :     ExprType returnType = instance()->debug().debugGetResultType(funcIndex());
     617           0 :     switch (returnType) {
     618             :       case ExprType::Void:
     619           0 :           cachedReturnJSValue_.setUndefined();
     620           0 :           break;
     621             :       case ExprType::I32:
     622           0 :           cachedReturnJSValue_.setInt32(resultI32_);
     623           0 :           break;
     624             :       case ExprType::I64:
     625             :           // Just display as a Number; it's ok if we lose some precision
     626           0 :           cachedReturnJSValue_.setDouble((double)resultI64_);
     627           0 :           break;
     628             :       case ExprType::F32:
     629           0 :           cachedReturnJSValue_.setDouble(JS::CanonicalizeNaN(resultF32_));
     630           0 :           break;
     631             :       case ExprType::F64:
     632           0 :           cachedReturnJSValue_.setDouble(JS::CanonicalizeNaN(resultF64_));
     633           0 :           break;
     634             :       default:
     635           0 :           MOZ_CRASH("result type");
     636             :     }
     637           0 : }
     638             : 
     639             : HandleValue
     640           0 : DebugFrame::returnValue() const
     641             : {
     642           0 :     MOZ_ASSERT(hasCachedReturnJSValue_);
     643           0 :     return HandleValue::fromMarkedLocation(&cachedReturnJSValue_);
     644             : }
     645             : 
     646             : void
     647           0 : DebugFrame::clearReturnJSValue()
     648             : {
     649           0 :     hasCachedReturnJSValue_ = true;
     650           0 :     cachedReturnJSValue_.setUndefined();
     651           0 : }
     652             : 
     653             : void
     654           0 : DebugFrame::observe(JSContext* cx)
     655             : {
     656           0 :    if (!observing_) {
     657           0 :        instance()->debug().adjustEnterAndLeaveFrameTrapsState(cx, /* enabled = */ true);
     658           0 :        observing_ = true;
     659             :    }
     660           0 : }
     661             : 
     662             : void
     663           0 : DebugFrame::leave(JSContext* cx)
     664             : {
     665           0 :     if (observing_) {
     666           0 :        instance()->debug().adjustEnterAndLeaveFrameTrapsState(cx, /* enabled = */ false);
     667           0 :        observing_ = false;
     668             :     }
     669           0 : }
     670             : 
     671           0 : CodeRange::CodeRange(Kind kind, Offsets offsets)
     672           0 :   : begin_(offsets.begin),
     673             :     ret_(0),
     674           0 :     end_(offsets.end),
     675             :     funcIndex_(0),
     676             :     funcLineOrBytecode_(0),
     677             :     funcBeginToNormalEntry_(0),
     678           0 :     kind_(kind)
     679             : {
     680           0 :     MOZ_ASSERT(begin_ <= end_);
     681             : #ifdef DEBUG
     682           0 :     switch (kind_) {
     683             :       case Entry:
     684             :       case DebugTrap:
     685             :       case FarJumpIsland:
     686             :       case Inline:
     687             :       case Throw:
     688             :       case Interrupt:
     689           0 :         break;
     690             :       case Function:
     691             :       case TrapExit:
     692             :       case ImportJitExit:
     693             :       case ImportInterpExit:
     694             :       case BuiltinThunk:
     695           0 :         MOZ_CRASH("should use more specific constructor");
     696             :     }
     697             : #endif
     698           0 : }
     699             : 
     700           0 : CodeRange::CodeRange(Kind kind, CallableOffsets offsets)
     701           0 :   : begin_(offsets.begin),
     702           0 :     ret_(offsets.ret),
     703           0 :     end_(offsets.end),
     704             :     funcIndex_(0),
     705             :     funcLineOrBytecode_(0),
     706             :     funcBeginToNormalEntry_(0),
     707           0 :     kind_(kind)
     708             : {
     709           0 :     MOZ_ASSERT(begin_ < ret_);
     710           0 :     MOZ_ASSERT(ret_ < end_);
     711             : #ifdef DEBUG
     712           0 :     switch (kind_) {
     713             :       case TrapExit:
     714             :       case ImportJitExit:
     715             :       case ImportInterpExit:
     716             :       case BuiltinThunk:
     717           0 :         break;
     718             :       case Entry:
     719             :       case DebugTrap:
     720             :       case FarJumpIsland:
     721             :       case Inline:
     722             :       case Throw:
     723             :       case Interrupt:
     724             :       case Function:
     725           0 :         MOZ_CRASH("should use more specific constructor");
     726             :     }
     727             : #endif
     728           0 : }
     729             : 
     730           0 : CodeRange::CodeRange(uint32_t funcIndex, uint32_t funcLineOrBytecode, FuncOffsets offsets)
     731           0 :   : begin_(offsets.begin),
     732           0 :     ret_(offsets.ret),
     733           0 :     end_(offsets.end),
     734             :     funcIndex_(funcIndex),
     735             :     funcLineOrBytecode_(funcLineOrBytecode),
     736           0 :     funcBeginToNormalEntry_(offsets.normalEntry - begin_),
     737           0 :     kind_(Function)
     738             : {
     739           0 :     MOZ_ASSERT(begin_ < ret_);
     740           0 :     MOZ_ASSERT(ret_ < end_);
     741           0 :     MOZ_ASSERT(offsets.normalEntry - begin_ <= UINT8_MAX);
     742           0 : }
     743             : 
     744             : const CodeRange*
     745           0 : wasm::LookupInSorted(const CodeRangeVector& codeRanges, CodeRange::OffsetInCode target)
     746             : {
     747           0 :     size_t lowerBound = 0;
     748           0 :     size_t upperBound = codeRanges.length();
     749             : 
     750             :     size_t match;
     751           0 :     if (!BinarySearch(codeRanges, lowerBound, upperBound, target, &match))
     752           0 :         return nullptr;
     753             : 
     754           0 :     return &codeRanges[match];
     755             : }

Generated by: LCOV version 1.13