diff --git a/01.GETTING-STARTED.md b/01.GETTING-STARTED.md index 04c0408c0..b17e117f4 100644 --- a/01.GETTING-STARTED.md +++ b/01.GETTING-STARTED.md @@ -67,13 +67,13 @@ The default libc is jerry-libc, but you can use compiler-default libc or an exte - compiler-default libc: ```bash -python tools/build.py --jerry-libc=off --compiler-default-libc=on +python tools/build.py --jerry-libc=off ``` - external libc: ```bash -python tools/build.py --jerry-libc=off --compiler-default-libc=off --compile-flag="-I/path/to/libc/include" +python tools/build.py --jerry-libc=off --compile-flag="-nostdlib -I/path/to/ext-libc/include" --link-lib="-lext-c" ``` **Add toolchain file** diff --git a/03.API-EXAMPLE.md b/03.API-EXAMPLE.md index 6cf324bf0..87248986b 100644 --- a/03.API-EXAMPLE.md +++ b/03.API-EXAMPLE.md @@ -521,4 +521,4 @@ Value of x is 17 ## Further steps -For further API description, please visit [API Reference page]({{ site.github.url }}/api-reference/) on [JerryScript home page]({{ site.github.url }}/). +For further API description, please visit [API Reference page](https://samsung.github.io/jerryscript/api-reference/) on [JerryScript home page](https://samsung.github.io/jerryscript/). diff --git a/04.INTERNALS.md b/04.INTERNALS.md index 50aaf2680..c3f36613f 100644 --- a/04.INTERNALS.md +++ b/04.INTERNALS.md @@ -246,7 +246,7 @@ simple value is a pre-defined constant which can be: Compressed pointers were introduced to save heap space. -{: class="thumbnail center-block img-responsive" } +{: class="thumbnail center-block img-responsive" } These pointers are 8 byte aligned 16 bit long pointers which can address 512 Kb of memory which is also the maximum size of the JerryScript heap. To support even more diff --git a/05.PORT-API.md b/05.PORT-API.md index 13a79f158..9fd88255e 100644 --- a/05.PORT-API.md +++ b/05.PORT-API.md @@ -77,13 +77,13 @@ typedef enum * of the parameter list. * * This function is only called with messages coming from the jerry engine as - * the result of some abnormal operation or describing its internal operations + * the result of some abnormal operation or describing its internal operations * (e.g., data structure dumps or tracing info). * * It should be the port that decides whether error and debug messages are logged to * the console, or saved to a database or to a file. - * - * Example: a libc-based port may implement this with vfprintf(stderr) or + * + * Example: a libc-based port may implement this with vfprintf(stderr) or * vfprintf(logfile), or both, depending on log level. */ void jerry_port_log (jerry_log_level_t level, const char *fmt, ...); diff --git a/06.REFERENCE-COUNTING.md b/06.REFERENCE-COUNTING.md new file mode 100644 index 000000000..9d296b226 --- /dev/null +++ b/06.REFERENCE-COUNTING.md @@ -0,0 +1,183 @@ +--- +layout: page +title: Reference counting +permalink: /reference-counting/ +--- + +* toc +{:toc} + +## Reference counting in JerryScript + +In JerryScript all `jerry_value_t` values are independent +references to internal objects. Values returned by JerryScript +API functions are always live references and must be released +by `jerry_release_value`. + +```c + jerry_value_t global = jerry_get_global_object (); + + /* The value stored in the 'global' variable contains a live + * reference to the global object. The system also keeps its + * own live reference to the global object. These two references + * are indepent, and both must be destroyed before the global + * object can be freed. */ + + jerry_release_value (global); + + /* Without jerry_release_value() the global object will not + * be freed even by jerry_cleanup(). After the reference + * is released it becomes a dead reference and cannot be + * used anymore. */ +``` + +Multiple references might refer to the same internal object +even though their `jerry_value_t` representation might be different. + +```c + jerry_value_t pi_ref1 = jerry_create_number (3.14); + jerry_value_t pi_ref2 = jerry_acquire_value (pi_ref1); + + /* Both pi_ref1 and pi_ref2 refer to the same 3.14 value + * although they might not be equal in C (pi_ref1 != pi_ref2). */ + + /* Both references must be released. */ + jerry_release_value (pi_ref1); + jerry_release_value (pi_ref2); +``` + +Releasing the same `jerry_value_t` twice to release two live +references is not allowed and it might cause crashes. Hence the +following code is an **INCORRECT WAY** of releasing the 3.14 value. + +```c + jerry_release_value (pi_ref1); + jerry_release_value (pi_ref1); +``` + +JerryScript API functions returning with a `jerry_value_t` always +return with a new live reference. Passing a `jerry_value_t` to +an API function never releases its reference. The next example +shows this behaviour through property getting and setting. + +```c + jerry_value_t prop_value = jerry_get_property (...); + + /* The prop_value must be released later because both the base + * object and the prop_value have an independent reference to + * the same JavaScript value. When the operation is failed + * the prop_value contains a live reference to an error object. + * This reference must be released as well. */ + + if (jerry_value_has_error_flag (prop_value)) + { + /* Errors can be handled here. */ + } + else + { + /* The application has a live reference to the property + * value even if the base object is freed by the garbage + * collector. */ + } + + /* The prop_value must be released. */ + jerry_release_value (prop_value); + + /* Property setting is the same. */ + + jerry_value_t result = jerry_set_property (..., new_prop_value); + + /* If the property set is successful a new reference is created + * for the value referenced by new_prop_value. The new_prop_value + * reference must be released regardless the operation is + * successful. */ + + /* The new_prop_value can be passed to other JerryScript API + * functions before the jerry_release_value () call. */ + + jerry_release_value (new_prop_value); + + /* The reference stored in 'result' variable contains whether + * the operation is successful and must also be freed. */ + + if (jerry_value_has_error_flag (result)) + { + /* Errors can be handled here. */ + } + else + { + /* A reference to a true primitive value is returned. */ + } + + jerry_release_value (result); +``` + +The simplest form of setting a property without error checking +is the following: + +```c + /* There are no 'ifs' in this snippet. */ + jerry_release_value (jerry_set_property (..., new_prop_value)); + jerry_release_value (new_prop_value); +``` + +The reference returned by a `jerry_external_handler_t` callback +transfers the ownership of the live reference. Otherwise the +referenced object could be freed by the garbage collector. + +```c +jerry_value_t my_external_handler (const jerry_value_t function_obj, + const jerry_value_t this_val, + const jerry_value_t args_p[], + const jerry_length_t args_count +{ + /* Do not release function_obj, this_val, and args_p because + * these references are automatically released after the handler + * is returned. This approach reduces code size which is useful + * on embedded systems. However you can create other references + * to them by calling jerry_acquire_value () if needed. */ + + /* Since the ownership of the reference is transferred to the + * caller the following snippet is valid. */ + + /* If the value to be returned is needed for other purposes the + * jerry_acquire_value () can be used to create new references. */ + return jerry_create_string (...); +} +``` + +Duplicating a `jerry_value_t` in C does not create another live reference. + +```c + jerry_value_t undef = jerry_create_undefined (); + jerry_value_t undef2 = undef; + + /* Releasing either undef or undef2 is valid but not both. + * After the release both references become dead (invalid). */ + jerry_release_value (undef2); + + /* Dead references can be reassigned again. */ + undef = jerry_create_boolean (true); +``` + +References can be duplicated in C as long as only one of them is freed. + +```c + jerry_value_t a = jerry_create_boolean (true); + + jerry_value_t b = a; + jerry_value_t c = a; + + /* A new reference is assigned to 'a'. */ + a = jerry_create_boolean (false); + + [...] + + jerry_release_value (a); + /* The 'a' (boolean false) reference becomes dead (invalid). */ + + jerry_release_value (c); + /* Both 'b' and 'c' (boolean true) references become dead. */ + + /* Since all references are released no memory leak is possible. */ +``` diff --git a/_includes/header.html b/_includes/header.html index 59f7f1c72..0bc8d4517 100644 --- a/_includes/header.html +++ b/_includes/header.html @@ -22,13 +22,26 @@