Skip to content
This repository was archived by the owner on Oct 15, 2020. It is now read-only.

Commit acb4225

Browse files
committed
chakrashim: Improve AddLocal codepath
`HandleScope` was simulated in chakrashim by saving references in `JavascriptArray` which involved calling `JsSetIndexedProperty` API. Although this API is not slow, but there is an overhead of calling JSRT APIs. It regress performance if `AddLocal` is called often. To avoid that, gathered elements in `_locals` stack and then bulk pushed them to array. * Earlier we called `JsCreateArray` with length 1 to create the above array. This creates an array of head segment size 4 (rounding) but since we are pushing `kOnStackLocals`, we would fill up the head segment and allocate newer segment. Instead if we pass length 0 to `JsCreateArray` it creates a head segment of size 16 and we don't have to initialize another segment till count reaches 16. * Also, I converted `Object::GetPropertyAttributes` to javascript function which should save 6 JSRT calls. I have also added `CHAKRA-TODO` comments for functions that should be easily converted to javascript functions. PR-URL: #101 Reviewed-By: Jianchun Xu <Jianchun.Xu@microsoft.com>
1 parent 581e929 commit acb4225

File tree

12 files changed

+76
-184
lines changed

12 files changed

+76
-184
lines changed

deps/chakrashim/include/v8.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -734,10 +734,11 @@ class V8_EXPORT HandleScope {
734734
private:
735735
friend class EscapableHandleScope;
736736
template <class T> friend class Local;
737-
static const int kOnStackLocals = 5; // Arbitrary number of refs on stack
737+
static const int kOnStackLocals = 8; // Arbitrary number of refs on stack
738738

739-
JsValueRef _locals[kOnStackLocals]; // Save some refs on stack
740-
JsValueRef _refs; // More refs go to a JS array
739+
// Save some refs on stack. 1st element on stack
740+
// is the JavascriptArray where other refs go.
741+
JsValueRef _locals[kOnStackLocals + 1];
741742
int _count;
742743
HandleScope *_prev;
743744
JsContextRef _contextRef;

deps/chakrashim/lib/chakra_shim.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,26 @@
568568
// CHAKRA-TODO: Need to add JSRT API to detect this
569569
return false;
570570
};
571+
utils.getPropertyAttributes = function(object, value) {
572+
var descriptor = Object_getOwnPropertyDescriptor(object, value);
573+
if (descriptor == undefined) {
574+
return -1;
575+
}
576+
577+
var attributes = 0;
578+
// taken from v8.h. Update if this changes in future
579+
const ReadOnly = 1, DontEnum = 2, DontDelete = 4;
580+
if (!descriptor.writable) {
581+
attributes |= ReadOnly;
582+
}
583+
if (!descriptor.enumerable) {
584+
attributes |= DontEnum;
585+
}
586+
if (!descriptor.configurable) {
587+
attributes |= DontDelete;
588+
}
589+
return attributes;
590+
};
571591
}
572592

573593
patchErrorTypes();

deps/chakrashim/src/jsrtcachedpropertyidref.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
DEF(apply)
3434
DEF(concat)
35+
DEF(push)
3536
DEF(construct)
3637
DEF(constructor)
3738
DEF(defineProperty)
@@ -72,6 +73,8 @@ DEF(getSymbolFor)
7273
DEF(ensureDebug)
7374
DEF(enqueueMicrotask)
7475
DEF(dequeueMicrotask)
76+
DEF(saveInHandleScope)
77+
DEF(getPropertyAttributes)
7578
DEF(getFunctionName)
7679
DEF(getFileName)
7780
DEF(getColumnNumber)

deps/chakrashim/src/jsrtcontextcachedobj.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ DEFTYPE(Number)
3333
DEFTYPE(Object)
3434
DEFTYPE(Proxy)
3535
DEFTYPE(String)
36+
DEFTYPE(Array)
3637
DEFTYPE(Uint8Array)
3738
DEFTYPE(Uint8ClampedArray)
3839
DEFTYPE(Int8Array)
@@ -46,9 +47,12 @@ DEFTYPE(Float64Array)
4647

4748

4849
// These prototype functions will be cached/shimmed
50+
DEFMETHOD(Object, getOwnPropertyDescriptor)
4951
DEFMETHOD(Object, hasOwnProperty)
5052
DEFMETHOD(Object, toString)
5153
DEFMETHOD(String, concat)
54+
DEFMETHOD(Array, push)
55+
5256

5357
#undef DEFTYPE
5458
#undef DEFMETHOD

deps/chakrashim/src/jsrtcontextshim.cc

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ ContextShim::ContextShim(IsolateShim * isolateShim,
7373
#undef DEF_IS_TYPE
7474
cloneObjectFunction(JS_INVALID_REFERENCE),
7575
getPropertyNamesFunction(JS_INVALID_REFERENCE),
76-
getOwnPropertyDescriptorFunction(JS_INVALID_REFERENCE),
7776
getEnumerableNamedPropertiesFunction(JS_INVALID_REFERENCE),
7877
getEnumerableIndexedPropertiesFunction(JS_INVALID_REFERENCE),
7978
createEnumerationIteratorFunction(JS_INVALID_REFERENCE),
@@ -86,7 +85,8 @@ ContextShim::ContextShim(IsolateShim * isolateShim,
8685
getSymbolForFunction(JS_INVALID_REFERENCE),
8786
ensureDebugFunction(JS_INVALID_REFERENCE),
8887
enqueueMicrotaskFunction(JS_INVALID_REFERENCE),
89-
dequeueMicrotaskFunction(JS_INVALID_REFERENCE) {
88+
dequeueMicrotaskFunction(JS_INVALID_REFERENCE),
89+
getPropertyAttributesFunction(JS_INVALID_REFERENCE) {
9090
memset(globalConstructor, 0, sizeof(globalConstructor));
9191
memset(globalPrototypeFunction, 0, sizeof(globalPrototypeFunction));
9292
}
@@ -302,16 +302,6 @@ bool ContextShim::InitializeBuiltIns() {
302302
return false;
303303
}
304304

305-
if (!InitializeBuiltIn(&getOwnPropertyDescriptorFunction,
306-
[this](JsValueRef * value) {
307-
return GetProperty(
308-
GetObjectConstructor(),
309-
CachedPropertyIdRef::getOwnPropertyDescriptor,
310-
value);
311-
})) {
312-
return false;
313-
}
314-
315305
if (DefineProperty(globalObject,
316306
GetIsolateShim()->GetKeepAliveObjectSymbolPropertyIdRef(),
317307
PropertyDescriptorOptionValues::False,
@@ -516,10 +506,14 @@ DECLARE_GETOBJECT(DateConstructor,
516506
DECLARE_GETOBJECT(ProxyConstructor,
517507
globalConstructor[GlobalType::Proxy])
518508
DECLARE_GETOBJECT(GetOwnPropertyDescriptorFunction,
519-
getOwnPropertyDescriptorFunction)
509+
globalPrototypeFunction[GlobalPrototypeFunction
510+
::Object_getOwnPropertyDescriptor])
520511
DECLARE_GETOBJECT(StringConcatFunction,
521512
globalPrototypeFunction[GlobalPrototypeFunction
522513
::String_concat])
514+
DECLARE_GETOBJECT(ArrayPushFunction,
515+
globalPrototypeFunction[GlobalPrototypeFunction
516+
::Array_push])
523517

524518

525519
JsValueRef ContextShim::GetProxyOfGlobal() {
@@ -571,6 +565,7 @@ CHAKRASHIM_FUNCTION_GETTER(getSymbolFor)
571565
CHAKRASHIM_FUNCTION_GETTER(ensureDebug)
572566
CHAKRASHIM_FUNCTION_GETTER(enqueueMicrotask);
573567
CHAKRASHIM_FUNCTION_GETTER(dequeueMicrotask);
568+
CHAKRASHIM_FUNCTION_GETTER(getPropertyAttributes);
574569

575570
#define DEF_IS_TYPE(F) CHAKRASHIM_FUNCTION_GETTER(F)
576571
#include "jsrtcachedpropertyidref.inc"

deps/chakrashim/src/jsrtcontextshim.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class ContextShim {
7272
JsValueRef GetGlobalType(GlobalType index);
7373
JsValueRef GetGetOwnPropertyDescriptorFunction();
7474
JsValueRef GetStringConcatFunction();
75+
JsValueRef GetArrayPushFunction();
7576
JsValueRef GetGlobalPrototypeFunction(GlobalPrototypeFunction index);
7677
JsValueRef GetProxyOfGlobal();
7778

@@ -124,10 +125,10 @@ class ContextShim {
124125
std::vector<void*> embedderData;
125126

126127
#define DECLARE_CHAKRASHIM_FUNCTION_GETTER(F) \
127-
public: \
128-
JsValueRef Get##F##Function(); \
129-
private: \
130-
JsValueRef F##Function; \
128+
public: \
129+
JsValueRef Get##F##Function(); \
130+
private: \
131+
JsValueRef F##Function; \
131132

132133
DECLARE_CHAKRASHIM_FUNCTION_GETTER(cloneObject);
133134
DECLARE_CHAKRASHIM_FUNCTION_GETTER(getPropertyNames);
@@ -144,6 +145,7 @@ class ContextShim {
144145
DECLARE_CHAKRASHIM_FUNCTION_GETTER(ensureDebug);
145146
DECLARE_CHAKRASHIM_FUNCTION_GETTER(enqueueMicrotask);
146147
DECLARE_CHAKRASHIM_FUNCTION_GETTER(dequeueMicrotask);
148+
DECLARE_CHAKRASHIM_FUNCTION_GETTER(getPropertyAttributes);
147149

148150
#define DEF_IS_TYPE(F) DECLARE_CHAKRASHIM_FUNCTION_GETTER(F)
149151
#include "jsrtcachedpropertyidref.inc"

deps/chakrashim/src/jsrtutils.cc

Lines changed: 2 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -282,102 +282,6 @@ JsErrorCode HasOwnProperty(JsValueRef object,
282282
return JsCallFunction(hasOwnPropertyFunction, args, _countof(args), result);
283283
}
284284

285-
JsErrorCode IsValueInArray(
286-
JsValueRef arrayRef,
287-
JsValueRef valueRef,
288-
std::function<JsErrorCode(JsValueRef, JsValueRef, bool*)> comparator,
289-
bool* result) {
290-
JsErrorCode error;
291-
unsigned int length;
292-
*result = false;
293-
error = GetArrayLength(arrayRef, &length);
294-
if (error != JsNoError) {
295-
return error;
296-
}
297-
298-
for (unsigned int index = 0; index < length; index++) {
299-
JsValueRef indexValue;
300-
error = JsIntToNumber(index, &indexValue);
301-
if (error != JsNoError) {
302-
return error;
303-
}
304-
305-
JsValueRef itemRef;
306-
error = JsGetIndexedProperty(arrayRef, indexValue, &itemRef);
307-
if (error != JsNoError) {
308-
return error;
309-
}
310-
311-
if (comparator != nullptr) {
312-
error = comparator(valueRef, itemRef, result);
313-
} else {
314-
error = JsEquals(itemRef, valueRef, result);
315-
}
316-
317-
if (error != JsNoError) {
318-
return error;
319-
}
320-
321-
if (*result)
322-
return JsNoError;
323-
}
324-
325-
return JsNoError;
326-
}
327-
328-
JsErrorCode IsValueInArray(JsValueRef arrayRef,
329-
JsValueRef valueRef,
330-
bool* result) {
331-
return IsValueInArray(arrayRef, valueRef, nullptr, result);
332-
}
333-
334-
JsErrorCode IsCaseInsensitiveStringValueInArray(JsValueRef arrayRef,
335-
JsValueRef valueRef,
336-
bool* result) {
337-
return IsValueInArray(arrayRef, valueRef, [=](
338-
JsValueRef first, JsValueRef second, bool* areEqual) -> JsErrorCode {
339-
JsValueType type;
340-
*areEqual = false;
341-
342-
JsErrorCode error = JsGetValueType(first, &type);
343-
if (error != JsNoError) {
344-
return error;
345-
}
346-
if (type != JsString) {
347-
return JsNoError;
348-
}
349-
350-
error = JsGetValueType(second, &type);
351-
if (error != JsNoError) {
352-
return error;
353-
}
354-
if (type != JsString) {
355-
return JsNoError;
356-
}
357-
358-
const wchar_t* firstPtr;
359-
size_t firstLength;
360-
361-
error = JsStringToPointer(first, &firstPtr, &firstLength);
362-
if (error != JsNoError) {
363-
return error;
364-
}
365-
366-
const wchar_t* secondPtr;
367-
size_t secondLength;
368-
369-
error = JsStringToPointer(second, &secondPtr, &secondLength);
370-
if (error != JsNoError) {
371-
return error;
372-
}
373-
374-
size_t maxCount = min(firstLength, secondLength);
375-
*areEqual = (_wcsnicmp(firstPtr, secondPtr, maxCount) == 0);
376-
return JsNoError;
377-
},
378-
result);
379-
}
380-
381285
JsErrorCode GetOwnPropertyDescriptor(JsValueRef ref,
382286
JsValueRef prop,
383287
JsValueRef* result) {
@@ -571,6 +475,7 @@ PropertyDescriptorOptionValues GetPropertyDescriptorOptionValue(bool b) {
571475
PropertyDescriptorOptionValues::False;
572476
}
573477

478+
// CHAKRA-TODO: Convert this function to javascript
574479
JsErrorCode CreatePropertyDescriptor(
575480
PropertyDescriptorOptionValues writable,
576481
PropertyDescriptorOptionValues enumerable,
@@ -911,6 +816,7 @@ bool DeletePrivate(JsValueRef object, JsValueRef key) {
911816
return hasDeleted;
912817
}
913818

819+
// CHAKRA-TODO: Convert this function to javascript
914820
JsErrorCode GetPrivate(JsValueRef object, JsValueRef key,
915821
JsValueRef *result) {
916822
JsPropertyIdRef hiddenValuesIdRef;

deps/chakrashim/src/jsrtutils.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,6 @@ JsErrorCode GetOwnPropertyDescriptor(JsValueRef ref,
101101
JsValueRef prop,
102102
JsValueRef* result);
103103

104-
JsErrorCode IsValueInArray(JsValueRef arrayRef,
105-
JsValueRef valueRef,
106-
bool* result);
107-
108-
JsErrorCode IsValueInArray(
109-
JsValueRef arrayRef,
110-
JsValueRef valueRef,
111-
std::function<JsErrorCode(JsValueRef, JsValueRef, bool*)> comperator,
112-
bool* result);
113-
114-
JsErrorCode IsCaseInsensitiveStringValueInArray(JsValueRef arrayRef,
115-
JsValueRef valueRef,
116-
bool* result);
117-
118104
JsErrorCode IsZero(JsValueRef value,
119105
bool *result);
120106

deps/chakrashim/src/v8chakra.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ bool TemplateData::Is(ExternalData* data) {
3737
|| data->GetType() == ExternalDataTypes::FunctionTemplateData;
3838
}
3939

40+
// CHAKRA-TODO: Convert this function to javascript?
4041
// Clone the template properties into the new instance
4142
JsErrorCode TemplateData::CopyPropertiesTo(JsValueRef newInstance) {
4243
if (properties.IsEmpty()) {
@@ -84,7 +85,7 @@ JsErrorCode TemplateData::CopyPropertiesTo(JsValueRef newInstance) {
8485
TemplateData* templateData = static_cast<TemplateData*>(data);
8586
value = templateData->NewInstance(value);
8687
if (value == JS_INVALID_REFERENCE) {
87-
return JsErrorFatal; // Just to indicate failed
88+
return JsErrorFatal; // Just to indicate failed
8889
}
8990
IfJsErrorRet(JsSetProperty(propertyDescriptor, valueIdRef, value, false));
9091
}

deps/chakrashim/src/v8handlescope.cc

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ __declspec(thread) HandleScope *current = nullptr;
2828
HandleScope::HandleScope(Isolate* isolate)
2929
: _prev(current),
3030
_locals(),
31-
_refs(JS_INVALID_REFERENCE),
3231
_count(0),
3332
_contextRef(JS_INVALID_REFERENCE),
3433
_addRefRecordHead(nullptr) {
34+
_locals[0] = JS_INVALID_REFERENCE;
3535
current = this;
3636
}
3737

@@ -54,28 +54,25 @@ HandleScope *HandleScope::GetCurrent() {
5454
}
5555

5656
bool HandleScope::AddLocal(JsValueRef value) {
57-
if (_count < _countof(_locals)) {
58-
_locals[_count++] = value;
59-
return true;
60-
}
61-
62-
if (_refs == JS_INVALID_REFERENCE) {
63-
if (JsCreateArray(1, &_refs) != JsNoError) {
64-
return AddLocalAddRef(value);
57+
// _locals is full, save them in _locals[0]
58+
if (_count == kOnStackLocals) {
59+
if (_locals[0] == JS_INVALID_REFERENCE) {
60+
if (JsCreateArray(0, &_locals[0]) != JsNoError) {
61+
return AddLocalAddRef(value);
62+
}
6563
}
66-
}
6764

68-
JsValueRef index;
65+
JsValueRef arrayPushFunction =
66+
jsrt::ContextShim::GetCurrent()->GetArrayPushFunction();
6967

70-
if (JsIntToNumber(_count - _countof(_locals), &index) != JsNoError) {
71-
return AddLocalAddRef(value);
72-
}
73-
74-
if (JsSetIndexedProperty(_refs, index, value) != JsNoError) {
75-
return AddLocalAddRef(value);
68+
JsValueRef result;
69+
if (JsCallFunction(arrayPushFunction, _locals,
70+
_countof(_locals), &result) != JsNoError) {
71+
return AddLocalAddRef(value);
72+
}
73+
_count = 0;
7674
}
77-
78-
_count++;
75+
_locals[1 + _count++] = value;
7976
return true;
8077
}
8178

0 commit comments

Comments
 (0)