From af00691d1ddee0b4b86dac44489f905edebb7a85 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Thu, 2 Oct 2014 19:30:36 +0400 Subject: [PATCH] Add this_arg dumping in parser --- src/libjsparser/parser.c | 61 ++++++++++++++++++++++++++++++--------- tests/jerry/N.this_arg.js | 26 +++++++++++++++++ 2 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 tests/jerry/N.this_arg.js diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 38ed5b649..f69d62e40 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -281,7 +281,7 @@ static void parse_expression (void); static void parse_statement (void); static void parse_assignment_expression (void); static void parse_source_element_list (void); -static void parse_argument_list (argument_list_type, idx_t); +static void parse_argument_list (argument_list_type, idx_t, idx_t); static uint8_t lp_string_hash (lp_string str) @@ -744,7 +744,7 @@ parse_property_assignment (void) NEXT (property_name); // push name skip_newlines (); - parse_argument_list (AL_FUNC_EXPR, next_temp_name ()); // push lhs + parse_argument_list (AL_FUNC_EXPR, next_temp_name (), INVALID_VALUE); // push lhs STACK_PUSH (U16, opcode_counter); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_FUNCTION_END, INVALID_VALUE, INVALID_VALUE); @@ -767,7 +767,7 @@ parse_property_assignment (void) NEXT (property_name); // push name skip_newlines (); - parse_argument_list (AL_FUNC_EXPR, next_temp_name ()); // push lhs + parse_argument_list (AL_FUNC_EXPR, next_temp_name (), INVALID_VALUE); // push lhs STACK_PUSH (U16, opcode_counter); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_FUNCTION_END, INVALID_VALUE, INVALID_VALUE); @@ -797,7 +797,7 @@ parse_property_assignment (void) For each ALT dumps appropriate bytecode. Uses OBJ during dump if neccesary. Returns temp var if expression has lhs, or 0 otherwise. */ static void -parse_argument_list (argument_list_type alt, idx_t obj) +parse_argument_list (argument_list_type alt, idx_t obj, idx_t this_arg) { // U8 open_tt, close_tt, args_count // IDX lhs, current_arg @@ -879,6 +879,12 @@ parse_argument_list (argument_list_type alt, idx_t obj) current_token_must_be (STACK_HEAD (U8, 3)); + if (alt == AL_CALL_EXPR && this_arg != INVALID_VALUE) + { + DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_THIS_ARG, this_arg, INVALID_VALUE); + STACK_INCR_HEAD (U8, 1); + } + skip_newlines (); while (!token_is (STACK_HEAD (U8, 2))) { @@ -1041,7 +1047,7 @@ parse_function_declaration (void) STACK_PUSH (IDX, token_data ()); skip_newlines (); - parse_argument_list (AL_FUNC_DECL, ID(1)); + parse_argument_list (AL_FUNC_DECL, ID(1), INVALID_VALUE); STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_UNDEFINED, INVALID_VALUE, INVALID_VALUE); @@ -1093,7 +1099,7 @@ parse_function_expression (void) } skip_newlines (); - parse_argument_list (AL_FUNC_EXPR, ID(1)); // push lhs + parse_argument_list (AL_FUNC_EXPR, ID(1), INVALID_VALUE); // push lhs STACK_PUSH (U16, OPCODE_COUNTER ()); DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_UNDEFINED, INVALID_VALUE, INVALID_VALUE); @@ -1127,7 +1133,7 @@ parse_array_literal (void) { STACK_DECLARE_USAGE (IDX) - parse_argument_list (AL_ARRAY_DECL, 0); + parse_argument_list (AL_ARRAY_DECL, 0, INVALID_VALUE); STACK_CHECK_USAGE_LHS (); } @@ -1140,7 +1146,7 @@ parse_object_literal (void) { STACK_DECLARE_USAGE (IDX) - parse_argument_list (AL_OBJ_DECL, 0); + parse_argument_list (AL_OBJ_DECL, 0, INVALID_VALUE); STACK_CHECK_USAGE_LHS ();; } @@ -1197,6 +1203,7 @@ parse_literal (void) : 'this' | Identifier | literal + | 'undefined' | '[' LT!* array_literal LT!* ']' | '{' LT!* object_literal LT!* '}' | '(' LT!* expression LT!* ')' @@ -1289,7 +1296,7 @@ cleanup: : '.' LT!* Identifier ; */ static void -parse_member_expression (void) +parse_member_expression (idx_t *this_arg) { // IDX obj, lhs, prop; STACK_DECLARE_USAGE (IDX) @@ -1300,10 +1307,18 @@ parse_member_expression (void) } else if (is_keyword (KW_NEW)) { - NEXT (member_expression); // push member + skip_newlines (); + parse_member_expression (this_arg); skip_newlines (); - parse_argument_list (AL_CONSTRUCT_EXPR, ID(1)); // push obj + if (this_arg) + { + parse_argument_list (AL_CONSTRUCT_EXPR, ID(1), *this_arg); // push obj + } + else + { + parse_argument_list (AL_CONSTRUCT_EXPR, ID(1), INVALID_VALUE); // push obj + } STACK_SWAP (IDX); STACK_DROP (IDX, 1); @@ -1316,6 +1331,11 @@ parse_member_expression (void) skip_newlines (); while (token_is (TOK_OPEN_SQUARE) || token_is (TOK_DOT)) { + if (this_arg) + { + *this_arg = ID (1); + } + STACK_PUSH (IDX, next_temp_name ()); if (token_is (TOK_OPEN_SQUARE)) @@ -1370,8 +1390,9 @@ parse_call_expression (void) { // IDX obj, lhs, prop; STACK_DECLARE_USAGE (IDX) + idx_t this_arg = INVALID_VALUE; - parse_member_expression (); + parse_member_expression (NULL); skip_newlines (); if (!token_is (TOK_OPEN_PAREN)) @@ -1380,7 +1401,17 @@ parse_call_expression (void) goto cleanup; } - parse_argument_list (AL_CALL_EXPR, ID(1)); // push lhs + TODO (/* Uncomment when interpreter will catch this properly. */) + // if (this_arg < lexer_get_reserved_ids_count ()) + // { + // STACK_PUSH (IDX, next_temp_name ()); + // DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_VARIABLE, this_arg); + // this_arg = ID(1); + // STACK_DROP (IDX, 1); + // } + + parse_argument_list (AL_CALL_EXPR, ID(1), this_arg); // push lhs + this_arg = INVALID_VALUE; STACK_SWAP (IDX); skip_newlines (); @@ -1392,12 +1423,13 @@ parse_call_expression (void) case TOK_OPEN_PAREN: { STACK_DROP (IDX, 1); - parse_argument_list (AL_CALL_EXPR, ID(1)); // push lhs + parse_argument_list (AL_CALL_EXPR, ID(1), this_arg); // push lhs skip_newlines (); break; } case TOK_OPEN_SQUARE: { + this_arg = ID (1); NEXT (expression); // push prop next_token_must_be (TOK_CLOSE_SQUARE); @@ -1409,6 +1441,7 @@ parse_call_expression (void) } case TOK_DOT: { + this_arg = ID (1); token_after_newlines_must_be (TOK_NAME); STACK_PUSH (IDX, token_data ()); diff --git a/tests/jerry/N.this_arg.js b/tests/jerry/N.this_arg.js new file mode 100644 index 000000000..678406c25 --- /dev/null +++ b/tests/jerry/N.this_arg.js @@ -0,0 +1,26 @@ +// Copyright 2014 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var i = 0; + +function a() {} + +a.prototype.b = function() { i++; } + +a.prototype.c = function() { this.b(); i++; } + +var aa = new a(); +aa.c(); + +assert (i === 2);