Skip to content

Commit

Permalink
[MERGE #432] module runtime change #3
Browse files Browse the repository at this point in the history
Merge pull request #432 from Yongqu:module
Implement the remaining operations in SourceTextModuleRecord, including   mainly ResolveExport and GetExportNames operations. Start implementation of ModuleNamespace. Implemented GetModuleNamespace. Detailed   namespace implementation is not in yet. Filled in some holes in earlier implementation, like error handling for top level operations,   notify the parent module if the current module failed in parse or ModuleDeclarationInitialization.   Export method for bytecode generator to retrieve the localexport slot information.   Fixed some potential memory leak by implementing the Finalize method for SourceTextModuleRecord. Temporary disable ModuleEvaluation for non-root modules, pending bytecode generator change.
  • Loading branch information
Yongqu committed Mar 5, 2016
2 parents 324affa + d210f0d commit 79b870a
Show file tree
Hide file tree
Showing 21 changed files with 1,524 additions and 952 deletions.
5 changes: 4 additions & 1 deletion lib/Parser/rterrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,7 @@ RT_ERROR_MSG(JSERR_RegExpExecInvalidReturnType, 5641, "%s: Return value of RegEx
RT_ERROR_MSG(JSERR_ProxyTrapReturnedFalse, 5642, "Proxy trap `%s` returned false", "Proxy trap returned false", kjstTypeError, 0)
RT_ERROR_MSG(JSERR_ModuleResolveExport, 5643, "Module export %s cannot be resolved", "Module export cannot be resolved", kjstSyntaxError, 0)
RT_ERROR_MSG(JSERR_TooManyImportExprots, 5644, "Module has too many import/export definitions", "Module has too many import/export definitions", kjstRangeError, 0)
RT_ERROR_MSG(JSERR_ObjectCoercible, 5645, "", "Cannot convert null or undefined to object", kjstTypeError, 0)
RT_ERROR_MSG(JSERR_CannotResolveModule, 5645, "HostResolveImportedModule failed to resolve module with specifier %s", "HostResolveImportedModule failed to resolve module", kjstReferenceError, 0)
RT_ERROR_MSG(JSERR_ResolveExportFailed, 5646, "Resolve export %s failed due to circular reference or resolved exports", "Resolve export failed due to circular reference or resolved exports", kjstSyntaxError, 0)

RT_ERROR_MSG(JSERR_ObjectCoercible, 5647, "", "Cannot convert null or undefined to object", kjstTypeError, 0)
1 change: 1 addition & 0 deletions lib/Runtime/Base/JnDirectFields.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ ENTRY(Uint8x16)
ENTRY(zero)
ENTRY(splat)
ENTRY2(bool_, L"bool") // "bool" cannot be an identifier in C++ so using "bool_" instead
ENTRY2(default_, L"default")

ENTRY(fromFloat32x4)

Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Language/Chakra.Runtime.Language.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)JavascriptNativeOperators.cpp" />
<ClCompile Include="ModuleNamespace.cpp" />
<ClCompile Include="SourceTextModuleRecord.cpp" />
</ItemGroup>
<ItemGroup>
Expand Down
22 changes: 22 additions & 0 deletions lib/Runtime/Language/Chakra.Runtime.Language.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@
<ClCompile Include="$(MSBuildThisFileDirectory)RuntimeLanguagePch.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JavascriptNativeOperators.cpp" />
<ClCompile Include="SourceTextModuleRecord.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdInt16x8Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdInt16x8OperationX86X64.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdUint32x4Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdUint32x4OperationX86X64.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdUint16x8Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdUint16x8OperationX86X64.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdUint8x16Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdUint8x16OperationX86X64.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdBool32x4Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdBool32x4OperationX86X64.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdBool16x8Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdBool16x8OperationX86X64.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdBool8x16Operation.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SimdBool8x16OperationX86X64.cpp" />
<ClCompile Include="ModuleNamespace.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AsmJs.h" />
Expand Down Expand Up @@ -124,6 +139,13 @@
<ClInclude Include="RuntimeLanguagePch.h" />
<ClInclude Include="SourceTextModuleRecord.h" />
<ClInclude Include="ModuleRecordBase.h" />
<ClInclude Include="SimdInt16x8Operation.h" />
<ClInclude Include="SimdUint32x4Operation.h" />
<ClInclude Include="SimdUint16x8Operation.h" />
<ClInclude Include="SimdUint8x16Operation.h" />
<ClInclude Include="SimdBool32x4Operation.h" />
<ClInclude Include="SimdBool16x8Operation.h" />
<ClInclude Include="SimdBool8x16Operation.h" />
</ItemGroup>
<ItemGroup>
<MASM Include="$(MSBuildThisFileDirectory)amd64\amd64_Thunks.asm">
Expand Down
114 changes: 114 additions & 0 deletions lib/Runtime/Language/ModuleNamespace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

#include "RuntimeLanguagePch.h"
#include "ModuleNamespace.h"
#include "Types\PropertyIndexRanges.h"
#include "Types\SimpleDictionaryPropertyDescriptor.h"
#include "Types\SimpleDictionaryTypeHandler.h"

namespace Js
{
ModuleNamespace::ModuleNamespace(ModuleRecordBase* moduleRecord, DynamicType* type) :
moduleRecord(moduleRecord), DynamicObject(type), unambiguousNonLocalExports(nullptr)
{

}

ModuleNamespace* ModuleNamespace::GetModuleNamespace(ModuleRecordBase* requestModule)
{
Assert(requestModule->IsSourceTextModuleRecord());
SourceTextModuleRecord* moduleRecord = static_cast<SourceTextModuleRecord*>(requestModule);
ModuleNamespace* nsObject = moduleRecord->GetNamespace();
if (nsObject != nullptr)
{
return nsObject;
}
ScriptContext* scriptContext = moduleRecord->GetRealm()->GetScriptContext();
RecyclableObject* nullValue = scriptContext->GetLibrary()->GetNull();
Recycler* recycler = scriptContext->GetRecycler();

ResolvedExportMap* resolvedExportMap = moduleRecord->GetExportedNamesMap();
if (resolvedExportMap == nullptr)
{
Assert(moduleRecord->GetLocalExportCount() == 0);
Assert(moduleRecord->GetIndirectExportEntryList() == nullptr);
Assert(moduleRecord->GetStarExportRecordList() == nullptr);
}

// First, the storage for local exports are stored in the ModuleRecord object itself, and we can build up a simpleDictionaryTypeHanlder to
// look them up locally.
SimpleDictionaryTypeHandlerNotExtensible* typeHandler = SimpleDictionaryTypeHandlerNotExtensible::New(recycler, moduleRecord->GetLocalExportCount(), 0, 0);
DynamicType* dynamicType = DynamicType::New(scriptContext, TypeIds_ModuleNamespace, nullValue, nullptr, typeHandler);
nsObject = RecyclerNew(recycler, ModuleNamespace, moduleRecord, dynamicType);

LocalExportIndexList* localExportIndexList = moduleRecord->GetLocalExportIndexList();
if (localExportIndexList != nullptr)
{
for (uint i = 0; i < (uint)localExportIndexList->Count(); i++)
{
#if DBG
ModuleNameRecord tempNameRecord;
Assert(moduleRecord->GetLocalExportSlotIndex(localExportIndexList->Item(i)) == i);
Assert(resolvedExportMap->TryGetValue(localExportIndexList->Item(i), &tempNameRecord) && tempNameRecord.module == moduleRecord);
#endif
nsObject->SetPropertyWithAttributes(localExportIndexList->Item(i), nullValue, PropertyModuleNamespaceDefault, nullptr);
}
}
// update the local slot to use the storage for local exports.
nsObject->SetAuxSlotsForModuleNS(moduleRecord->GetLocalExportSlots());

// For items that are not in the local export list, we need to resolve them to get it
ExportedNames* exportedName = moduleRecord->GetExportedNames(nullptr);
ModuleNameRecord* moduleNameRecord = nullptr;
#if DBG
uint unresolvableExportsCount = 0;
#endif
exportedName->Map([&](PropertyId propertyId) {
if (!moduleRecord->ResolveExport(propertyId, nullptr, nullptr, &moduleNameRecord))
{
// ignore ambigious resolution.
#if DBG
unresolvableExportsCount++;
#endif
return;
}
// non-ambiguous resolution.
if (moduleNameRecord == nullptr)
{
JavascriptError::ThrowSyntaxError(scriptContext, JSERR_ResolveExportFailed, scriptContext->GetPropertyName(propertyId)->GetBuffer());
}
if (moduleNameRecord->module == requestModule)
{
// skip local exports as they are covered in the localExportSlots.
return;
}
Assert(moduleNameRecord->module != moduleRecord);
nsObject->AddUnambiguousNonLocalExport(propertyId, moduleNameRecord);
});
#if DBG
uint totalExportCount = (moduleRecord->GetExportedNames(nullptr) != nullptr) ? moduleRecord->GetExportedNames(nullptr)->Count() : 0;
uint localExportCount = moduleRecord->GetLocalExportCount();
uint unambiguousNonLocalCount = (nsObject->GetUnambiguousNonLocalExports() != nullptr) ? nsObject->GetUnambiguousNonLocalExports()->Count() : 0;
Assert(totalExportCount == localExportCount + unambiguousNonLocalCount + unresolvableExportsCount);
#endif
BOOL result = nsObject->PreventExtensions();
Assert(result);
return nullptr;
// TODO: enable after actual namespace object implementation.
//return nsObject;
}

void ModuleNamespace::AddUnambiguousNonLocalExport(PropertyId propertyId, ModuleNameRecord* nonLocalExportNameRecord)
{
Recycler* recycler = GetScriptContext()->GetRecycler();
if (unambiguousNonLocalExports == nullptr)
{
unambiguousNonLocalExports = RecyclerNew(recycler, UnambiguousExportMap, recycler, 4);
}
// keep a local copy of the module/
unambiguousNonLocalExports->AddNew(propertyId, *nonLocalExportNameRecord);
}
}
74 changes: 69 additions & 5 deletions lib/Runtime/Language/ModuleNamespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,78 @@

namespace Js
{
/// Module namespace object
// This object, while the object is special that the properties are indirect bindings referencing variable
// definitions from different module, we can add the properties to the object and [[get]] them accordingly.
class ModuleNamespace : public DynamicObject
{
typedef JsUtil::BaseDictionary<PropertyId, ModuleNameRecord, RecyclerLeafAllocator, PowerOf2SizePolicy> UnambiguousExportMap;

protected:
DEFINE_VTABLE_CTOR(ModuleNamespace, DynamicObject);
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(ModuleNamespace);

protected:
ModuleNamespace(ModuleRecordBase* moduleRecord, DynamicType * type);
static ModuleNamespace* New(ModuleRecordBase* moduleRecord);
public:
ModuleNamespace();
private:
static ModuleNamespace* GetModuleNamespace(ModuleRecordBase* moduleRecord);

static bool Is(Var ns) { return ModuleNamespace::Is(ns); }

//virtual int GetPropertyCount() override;
//virtual PropertyId GetPropertyId(PropertyIndex index) override;
//virtual PropertyId GetPropertyId(BigPropertyIndex index) override;
//virtual BOOL HasProperty(PropertyId propertyId) override;
//virtual BOOL HasOwnProperty(PropertyId propertyId) override;
//virtual BOOL GetProperty(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
//virtual BOOL GetProperty(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
//virtual BOOL GetInternalProperty(Var instance, PropertyId internalPropertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
//virtual BOOL GetPropertyReference(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
//virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
//virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override { return false; }
//virtual BOOL SetInternalProperty(PropertyId internalPropertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override { return false; }
//virtual DescriptorFlags GetSetter(PropertyId propertyId, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
//virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var *setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
//virtual BOOL InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags = PropertyOperation_None, PropertyValueInfo* info = nullptr) override { return false; }
//virtual BOOL SetPropertyWithAttributes(PropertyId propertyId, Var value, PropertyAttributes attributes, PropertyValueInfo* info, PropertyOperationFlags flags = PropertyOperation_None, SideEffects possibleSideEffects = SideEffects_Any) override { return false; }
//virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags) override;
//virtual BOOL IsFixedProperty(PropertyId propertyId) override;
virtual BOOL HasItem(uint32 index) override { return false; }
virtual BOOL HasOwnItem(uint32 index) override { return false; }
virtual BOOL GetItem(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override { return false; }
virtual BOOL GetItemReference(Var originalInstance, uint32 index, Var* value, ScriptContext * requestContext) override { return false; }
virtual DescriptorFlags GetItemSetter(uint32 index, Var* setterValue, ScriptContext* requestContext) override { *setterValue = nullptr; return DescriptorFlags::None; }
//virtual BOOL SetItem(uint32 index, Var value, PropertyOperationFlags flags) override;
//virtual BOOL DeleteItem(uint32 index, PropertyOperationFlags flags) override;
//virtual BOOL ToPrimitive(JavascriptHint hint, Var* result, ScriptContext * requestContext) override;
//virtual BOOL GetEnumerator(BOOL enumNonEnumerable, Var* enumerator, ScriptContext* scriptContext, bool preferSnapshotSemantics = true, bool enumSymbols = false) override;
virtual BOOL SetAccessors(PropertyId propertyId, Var getter, Var setter, PropertyOperationFlags flags = PropertyOperation_None) override { return false; }
virtual BOOL GetAccessors(PropertyId propertyId, Var *getter, Var *setter, ScriptContext * requestContext) override { return false; }
virtual BOOL IsWritable(PropertyId propertyId) override { return true; }
virtual BOOL IsConfigurable(PropertyId propertyId) override { return false; }
virtual BOOL IsEnumerable(PropertyId propertyId) override { return true; }
virtual BOOL SetEnumerable(PropertyId propertyId, BOOL value) override { return false; }
virtual BOOL SetWritable(PropertyId propertyId, BOOL value) override { return false; }
virtual BOOL SetConfigurable(PropertyId propertyId, BOOL value) override { return false; }
//virtual BOOL SetAttributes(PropertyId propertyId, PropertyAttributes attributes) override;
virtual BOOL IsExtensible() override { return false; };
virtual BOOL PreventExtensions() override { return true; }
//virtual BOOL Seal() override;
//virtual BOOL Freeze() override;
virtual BOOL IsSealed() override { return true; }
virtual BOOL IsFrozen() override { return true; }
//virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
//virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
//virtual Var GetTypeOfString(ScriptContext * requestContext) override;

//virtual void RemoveFromPrototype(ScriptContext * requestContext) override;
//virtual void AddToPrototype(ScriptContext * requestContext) override;
virtual void SetPrototype(RecyclableObject* newPrototype) override { return; }

private:
ModuleRecordBase* moduleRecord;
UnambiguousExportMap* unambiguousNonLocalExports;
// this is a special case where we can override the slot to the "export slots".
void SetAuxSlotsForModuleNS(Var* auxSlot) { this->auxSlots = auxSlot; }
void AddUnambiguousNonLocalExport(PropertyId exportId, ModuleNameRecord* nonLocalExportNameRecord);
UnambiguousExportMap* GetUnambiguousNonLocalExports() const { return unambiguousNonLocalExports; }
};
}
29 changes: 16 additions & 13 deletions lib/Runtime/Language/ModuleRecordBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@

namespace Js
{
class ModuleRecordBase;
typedef SList<PropertyId> ExportedNames;
typedef SList<ModuleRecordBase*> ExportModuleRecordList;
typedef struct ModuleNameRecord
{
ModuleRecordBase* module;
PropertyId bindingName;
};
typedef SList<ModuleNameRecord> ResolveSet;

// ModuleRecord need to keep rootFunction etc. alive.
class ModuleRecordBase : FinalizableObject
class ModuleRecordBase : public FinalizableObject
{
public:
const unsigned long ModuleMagicNumber = *(const unsigned long*)"Mode";
typedef SList<PropertyId> ExportedNames;
typedef JsUtil::BaseDictionary<ModuleRecordBase*, PropertyId, ArenaAllocator, PrimeSizePolicy> ResolutionDictionary;
typedef SList<ModuleRecordBase*> ResolveSet;
typedef struct ModuleNameRecord
{
ModuleRecordBase* module;
PropertyId bindingName;
};

ModuleRecordBase(JavascriptLibrary* library) :
namespaceObject(nullptr), wasEvaluated(false),
javascriptLibrary(library), magicNumber(ModuleMagicNumber){};
Expand All @@ -29,11 +30,13 @@ namespace Js
ModuleNamespace* GetNamespace() { return namespaceObject; }
void SetNamespace(ModuleNamespace* moduleNamespace) { namespaceObject = moduleNamespace; }

virtual ExportedNames* GetExportedNames(ResolveSet* exportStarSet) = 0;
// return false when "ambiguous". otherwise exportRecord.
virtual bool ResolveExport(PropertyId exportName, ResolutionDictionary* resolveSet, ResolveSet* exportStarSet, ModuleNameRecord** exportRecord) = 0;
virtual ExportedNames* GetExportedNames(ExportModuleRecordList* exportStarSet) = 0;
// return false when "ambiguous".
// otherwise nullptr means "null" where we have circular reference/cannot resolve.
virtual bool ResolveExport(PropertyId exportName, ResolveSet* resolveSet, ExportModuleRecordList* exportStarSet, ModuleNameRecord** exportRecord) = 0;
virtual void ModuleDeclarationInstantiation() = 0;
virtual Var ModuleEvaluation() = 0;
virtual bool IsSourceTextModuleRecord() { return false; }

protected:
unsigned long magicNumber;
Expand Down
Loading

0 comments on commit 79b870a

Please sign in to comment.