Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions docs/workflow/building/coreclr/wasm.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ This will start a local HTTP server and you can open the provided URL in your br
You can also run the runtime directly in Node.js:

```bash
cd artifacts/bin/coreclr/browser.wasm.Debug/
node ./corerun.js -c /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/helloworld.dll
cp /runtime3/artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net10.0/*.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL
cp helloworld.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL
cd /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/
node ./corerun.js -c /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll
```

Note that path in the `args` need to be absolute path on your host file system in unix format (even on Windows).
Note that path in the node args need to be **absolute path** on your host file system in **unix format** (even on Windows).

## Debugging

Expand Down Expand Up @@ -109,11 +111,10 @@ VS Code, through Node.js, provides a good debugging option for WebAssembly CoreC
"outputCapture": "std",
"program": "corerun.js",
"env": {
"PAL_DBG_CHANNELS": "+all.all"
"PAL_DBG_CHANNELS": "+all.all",
"CORE_ROOT":"/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/"
},
"args": [
"-c",
"/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/",
"/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll"
],
"cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/"
Expand All @@ -122,12 +123,14 @@ VS Code, through Node.js, provides a good debugging option for WebAssembly CoreC
}
```

Note that path in the `args` need to be absolute path on your host file system in unix format (even on Windows).
Note that path in the `args` and `CORE_ROOT` need to be **absolute path** on your host file system in **unix format** (even on Windows).

3. **Set breakpoints** in `corewasmrun.js` in one of the `put_char` functions (the `stdout`/`stderr` implementation)
3. **Copy managed DLLs** `System.Runtime.dll` and `helloworld.dll` into `artifacts/bin/coreclr/browser.wasm.Debug/IL/`.

4. **Start debugging** and step through the WebAssembly code using the call stack
4. **Set breakpoints** in `corewasmrun.js` in one of the `put_char` functions (the `stdout`/`stderr` implementation)

5. **Start debugging** and step through the WebAssembly code using the call stack

This approach allows you to debug the JavaScript host and step into WebAssembly code or into the C/C++ code if the Dwarf Debugging extension was installed.

5. to display `WCHAR *` strings in debugger watch window, cast it to `char16_t*` like `(char16_t*)pLoaderModule->m_fileName`
6. to display `WCHAR *` strings in debugger watch window, cast it to `char16_t*` like `(char16_t*)pLoaderModule->m_fileName`
8 changes: 4 additions & 4 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1093,13 +1093,13 @@ void InterpCompiler::BuildGCInfo(InterpMethod *pInterpMethod)
}

gcInfoEncoder->SetSizeOfStackOutgoingAndScratchArea(0);

if (m_compHnd->getMethodAttribs(m_methodInfo->ftn) & CORINFO_FLG_SHAREDINST)
{
if ((m_methodInfo->options & CORINFO_GENERICS_CTXT_MASK) != CORINFO_GENERICS_CTXT_FROM_THIS)
{
assert(paramType != GENERIC_CONTEXTPARAM_NONE);

int32_t genericArgStackOffset = m_pVars[getParamArgIndex()].offset;
INTERP_DUMP("SetGenericsInstContextStackSlot at %u\n", (unsigned)genericArgStackOffset);
gcInfoEncoder->SetPrologSize(4); // Size of 1 instruction
Expand Down Expand Up @@ -3016,7 +3016,7 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
if (iLogicalArg != 0 || !callInfo.sig.hasThis() || newObj)
{
CORINFO_CLASS_HANDLE classHandle;

// Implement the implicit argument conversion rules of III.1.6
switch (m_pStackPointer[iCurrentStackArg].type)
{
Expand Down Expand Up @@ -3062,7 +3062,7 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
break;
}
break;
// TODO-Interp, for 64bit Big endian platforms, we may need to implement the
// TODO-Interp, for 64bit Big endian platforms, we may need to implement the
// truncation rules for NativeInt/NativeUInt to I4/U4. However, on little-endian
// platforms, the interpreter calling convention will naturally produce the
// truncation, so there is no additional code necessary.
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/GCHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,11 +617,11 @@ static Object* GcAllocInternal(MethodTable* pEEType, uint32_t uFlags, uintptr_t
if (pObject == NULL)
return NULL;

pObject->set_EEType(pEEType);
pObject->SetMethodTable(pEEType);
if (pEEType->HasComponentSize())
{
ASSERT(numElements == (uint32_t)numElements);
((Array*)pObject)->InitArrayLength((uint32_t)numElements);
((Array*)pObject)->SetNumComponents((uint32_t)numElements);
}

if (isSampled)
Expand Down
10 changes: 1 addition & 9 deletions src/coreclr/nativeaot/Runtime/ObjectLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@
#include "ObjectLayout.h"
#include "MethodTable.inl"

#ifndef DACCESS_COMPILE
void Object::InitEEType(MethodTable * pEEType)
{
ASSERT(NULL == m_pEEType);
m_pEEType = pEEType;
}
#endif

uint32_t Array::GetArrayLength()
{
return m_Length;
Expand All @@ -37,7 +29,7 @@ void* Array::GetArrayData()
}

#ifndef DACCESS_COMPILE
void Array::InitArrayLength(uint32_t length)
void Array::SetNumComponents(uint32_t length)
{
m_Length = length;
}
Expand Down
7 changes: 3 additions & 4 deletions src/coreclr/nativeaot/Runtime/ObjectLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ class Object
#endif
ObjHeader * GetHeader() { return dac_cast<DPTR(ObjHeader)>(dac_cast<TADDR>(this) - SYNC_BLOCK_SKEW); }
#ifndef DACCESS_COMPILE
void set_EEType(MethodTable * pEEType)
void SetMethodTable(MethodTable * pEEType)
{ m_pEEType = pEEType; }
void InitEEType(MethodTable * pEEType);

size_t GetSize();
#endif
Expand Down Expand Up @@ -85,16 +84,16 @@ static uintptr_t const REFERENCE_SIZE = sizeof(Object *);
//-------------------------------------------------------------------------------------------------
class Array : public Object
{
friend class ArrayBase;
friend class AsmOffsets;

protected:
uint32_t m_Length;
#if defined(HOST_64BIT)
uint32_t m_uAlignpad;
#endif // HOST_64BIT
public:
uint32_t GetArrayLength();
void InitArrayLength(uint32_t length);
void SetNumComponents(uint32_t length);
void* GetArrayData();
};
typedef DPTR(Array) PTR_Array;
Expand Down
20 changes: 10 additions & 10 deletions src/coreclr/nativeaot/Runtime/portable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ FCIMPL1(Object *, RhpNewFast, MethodTable* pEEType)
{
acontext->alloc_ptr = alloc_ptr + size;
Object* pObject = (Object *)alloc_ptr;
pObject->set_EEType(pEEType);
pObject->SetMethodTable(pEEType);
return pObject;
}

Expand Down Expand Up @@ -118,8 +118,8 @@ FCIMPL2(Array *, RhpNewArrayFast, MethodTable * pArrayEEType, int numElements)
{
acontext->alloc_ptr = alloc_ptr + size;
Array* pObject = (Array*)alloc_ptr;
pObject->set_EEType(pArrayEEType);
pObject->InitArrayLength((uint32_t)numElements);
pObject->SetMethodTable(pArrayEEType);
pObject->SetNumComponents((uint32_t)numElements);
return pObject;
}

Expand Down Expand Up @@ -174,11 +174,11 @@ FCIMPL1(Object*, RhpNewFastAlign8, MethodTable* pEEType)
if (requiresPadding)
{
Object* dummy = (Object*)alloc_ptr;
dummy->set_EEType(g_pFreeObjectEEType);
dummy->SetMethodTable(g_pFreeObjectEEType);
alloc_ptr += 12;
}
Object* pObject = (Object *)alloc_ptr;
pObject->set_EEType(pEEType);
pObject->SetMethodTable(pEEType);
return pObject;
}

Expand Down Expand Up @@ -209,11 +209,11 @@ FCIMPL1(Object*, RhpNewFastMisalign, MethodTable* pEEType)
if (requiresPadding)
{
Object* dummy = (Object*)alloc_ptr;
dummy->set_EEType(g_pFreeObjectEEType);
dummy->SetMethodTable(g_pFreeObjectEEType);
alloc_ptr += 12;
}
Object* pObject = (Object *)alloc_ptr;
pObject->set_EEType(pEEType);
pObject->SetMethodTable(pEEType);
return pObject;
}

Expand Down Expand Up @@ -259,12 +259,12 @@ FCIMPL2(Array*, RhpNewArrayFastAlign8, MethodTable* pArrayEEType, int numElement
if (requiresAlignObject)
{
Object* dummy = (Object*)alloc_ptr;
dummy->set_EEType(g_pFreeObjectEEType);
dummy->SetMethodTable(g_pFreeObjectEEType);
alloc_ptr += 12;
}
Array* pObject = (Array*)alloc_ptr;
pObject->set_EEType(pArrayEEType);
pObject->InitArrayLength((uint32_t)numElements);
pObject->SetMethodTable(pArrayEEType);
pObject->SetNumComponents((uint32_t)numElements);
return pObject;
}

Expand Down
67 changes: 61 additions & 6 deletions src/coreclr/runtime/portable/AllocFast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,65 @@

#include <fcall.h>

extern void RhExceptionHandling_FailedAllocation(MethodTable *pMT, bool isOverflow);

EXTERN_C FCDECL2(Object*, RhpNewVariableSizeObject, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size)
{
PORTABILITY_ASSERT("RhpNewVariableSizeObject is not yet implemented");
return nullptr;
}

static Object* _RhpNewArrayFastCore(CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size)
{
FCALL_CONTRACT;
_ASSERTE(typeHnd_ != NULL);
_ASSERTE(size < INT32_MAX);

MethodTable* pMT = (MethodTable*)typeHnd_;
Thread* thread = GetThread();
ee_alloc_context* cxt = thread->GetEEAllocContext();

size_t sizeInBytes = (size_t)pMT->GetBaseSize() + ((size_t)size * (size_t)pMT->RawGetComponentSize());
sizeInBytes = ALIGN_UP(sizeInBytes, sizeof(void*));

uint8_t* alloc_ptr = cxt->getAllocPtr();
ASSERT(alloc_ptr <= cxt->getAllocLimit());
if ((size_t)(cxt->getAllocLimit() - alloc_ptr) >= sizeInBytes)
{
cxt->setAllocPtr(alloc_ptr + sizeInBytes);
PtrArray* pObject = (PtrArray *)alloc_ptr;
pObject->SetMethodTable(pMT);
pObject->SetNumComponents((INT32)size);
return pObject;
}

return RhpNewVariableSizeObject(typeHnd_, size);
}

EXTERN_C FCDECL2(Object*, RhpNewArrayFast, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size)
{
PORTABILITY_ASSERT("RhpNewArrayFast is not yet implemented");
return nullptr;
FCALL_CONTRACT;
_ASSERTE(typeHnd_ != NULL);

MethodTable* pMT = (MethodTable*)typeHnd_;

#ifndef HOST_64BIT
// if the element count is <= 0x10000, no overflow is possible because the component size is
// <= 0xffff, and thus the product is <= 0xffff0000, and the base size is only ~12 bytes
if (size > 0x10000)
{
// Overflow here should result in an OOM. Let the slow path take care of it.
return RhpNewVariableSizeObject(typeHnd_, size);
}
#endif // !HOST_64BIT

return _RhpNewArrayFastCore(typeHnd_, size);
}

EXTERN_C FCDECL2(Object*, RhpNewPtrArrayFast, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size)
{
PORTABILITY_ASSERT("RhpNewPtrArrayFast is not yet implemented");
return nullptr;
WRAPPER_NO_CONTRACT;
return RhpNewArrayFast(typeHnd_, size);
}

EXTERN_C FCDECL1(Object*, RhpNewFast, CORINFO_CLASS_HANDLE typeHnd_)
Expand All @@ -46,8 +89,20 @@ EXTERN_C FCDECL1(Object*, RhpNewFastMisalign, CORINFO_CLASS_HANDLE typeHnd_)
return nullptr;
}

#define MAX_STRING_LENGTH 0x3FFFFFDF

EXTERN_C FCDECL2(Object*, RhNewString, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR stringLength)
{
PORTABILITY_ASSERT("RhNewString is not yet implemented");
return nullptr;
FCALL_CONTRACT;
_ASSERTE(typeHnd_ != NULL);

MethodTable* pMT = (MethodTable*)typeHnd_;

if (stringLength > MAX_STRING_LENGTH)
{
RhExceptionHandling_FailedAllocation(pMT, false);
return NULL;
}

return _RhpNewArrayFastCore(typeHnd_, stringLength);
}
2 changes: 1 addition & 1 deletion src/coreclr/vm/callstubgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ CallStubHeader *CallStubGenerator::GenerateCallStubForSig(MetaSig &sig)
// Allocate space for the routines. The size of the array is conservatively set to twice the number of arguments
// plus one slot for the target pointer and reallocated to the real size at the end.
size_t tempStorageSize = ComputeTempStorageSize(sig);
PCODE *pRoutines = (PCODE*)alloca(ComputeTempStorageSize(sig));
PCODE *pRoutines = (PCODE*)alloca(tempStorageSize);
memset(pRoutines, 0, tempStorageSize);

m_interpreterToNative = true; // We always generate the interpreter to native call stub here
Expand Down
Loading