>From 1a2422e2b9591b99154c888c09d510f1dfef43c9 Mon Sep 17 00:00:00 2001 From: Gwenael Casaccio Date: Mon, 27 May 2013 10:30:36 +0200 Subject: [PATCH 1/2] Add debug information --- kernel/CompildCode.st | 20 +++++++++- kernel/DebugInformation.st | 64 ++++++++++++++++++++++++++++++ libgst/comp.c | 77 ++++++++++++++++++++++++++++++++++-- libgst/comp.h | 2 + libgst/dict.c | 11 ++++-- libgst/dict.h | 1 + libgst/files.c | 2 + packages.xml | 1 + packages/stinst/parser/STCompiler.st | 7 ++++ tests/compiler.ok | 7 ++++ tests/compiler.st | 19 +++++++++ tests/stcompiler.ok | 7 ++++ tests/stcompiler.st | 20 ++++++++++ 13 files changed, 231 insertions(+), 7 deletions(-) create mode 100644 kernel/DebugInformation.st diff --git a/kernel/CompildCode.st b/kernel/CompildCode.st index f42034f..fcbfe1d 100644 --- a/kernel/CompildCode.st +++ b/kernel/CompildCode.st @@ -33,7 +33,7 @@ ArrayedCollection subclass: CompiledCode [ - | literals header | + | literals header debugInfo | @@ -314,6 +314,12 @@ superclass for blocks and methods'> ^0 ] + arguments [ + + + ^ debugInfo arguments + ] + numArgs [ "Answer the number of arguments for the receiver" @@ -321,6 +327,12 @@ superclass for blocks and methods'> self subclassResponsibility ] + temporaries [ + + + ^ debugInfo temporaries + ] + numTemps [ "Answer the number of temporaries for the receiver" @@ -1076,6 +1088,12 @@ superclass for blocks and methods'> ^0 ] + debugInformation: aDebugInformation [ + + + ^ debugInfo := aDebugInformation + ] + discardTranslation [ "Flush the just-in-time translated code for the receiver (if any)." diff --git a/kernel/DebugInformation.st b/kernel/DebugInformation.st new file mode 100644 index 0000000..5297164 --- /dev/null +++ b/kernel/DebugInformation.st @@ -0,0 +1,64 @@ +"====================================================================== +| +| Object Method Definitions +| +| + ======================================================================" + +"====================================================================== +| +| Copyright 2013 Free Software Foundation, Inc. +| Written by Gwenael Casaccio. +| +| This file is part of the GNU Smalltalk class library. +| +| The GNU Smalltalk class library is free software; you can redistribute it +| and/or modify it under the terms of the GNU Lesser General Public License +| as published by the Free Software Foundation; either version 2.1, or (at +| your option) any later version. +| +| The GNU Smalltalk class library is distributed in the hope that it will be +| useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +| General Public License for more details. +| +| You should have received a copy of the GNU Lesser General Public License +| along with the GNU Smalltalk class library; see the file COPYING.LIB. +| If not, write to the Free Software Foundation, 59 Temple Place - Suite +| 330, Boston, MA 02110-1301, USA. +| + ======================================================================" + + +Object subclass: DebugInformation [ + + DebugInformation class >> args: anArgsArray temps: aTempsArray [ + + + ^ self new + args: anArgsArray temps: aTempsArray; + yourself + ] + + | args temps | + + args: anArgsArray temps: aTempsArray [ + + + args := anArgsArray. + temps := aTempsArray. + ] + + arguments [ + + + ^ args + ] + + temporaries [ + + + ^ temps + ] +] + diff --git a/libgst/comp.c b/libgst/comp.c index 10330e1..ac830e4 100644 --- a/libgst/comp.c +++ b/libgst/comp.c @@ -692,6 +692,10 @@ _gst_compile_method (tree_node method, OOP methodOOP; bc_vector bytecodes; int stack_depth; + int i, argCount, tempCount; + OOP argsOOP, tempsOOP, debugInfo; + gst_object object; + tree_node args; inc_ptr incPtr; gst_compiled_method compiledMethod; @@ -738,14 +742,14 @@ _gst_compile_method (tree_node method, methodOOP = _gst_nil_oop; if (setjmp (_gst_compiler_state->bad_method) == 0) { - if (_gst_declare_arguments (method->v_method.selectorExpr) == -1) + if ((argCount = _gst_declare_arguments (method->v_method.selectorExpr)) == -1) { _gst_errorf_at (method->location.first_line, "duplicate argument name"); EXIT_COMPILATION (); } - if (_gst_declare_temporaries (method->v_method.temporaries) == -1) + if ((tempCount = _gst_declare_temporaries (method->v_method.temporaries)) == -1) { _gst_errorf_at (method->location.first_line, "duplicate temporary variable name"); @@ -826,6 +830,44 @@ _gst_compile_method (tree_node method, selector, method->v_method.currentCategory, method->location.file_offset, method->v_method.endPos); + + + if (methodOOP != _gst_nil_oop) { + object = new_instance_with (_gst_array_class, argCount, &argsOOP); + INC_ADD_OOP (argsOOP); + + args = method->v_method.selectorExpr; + + if (args->nodeType == TREE_BINARY_EXPR) + { + object->data[0] = _gst_intern_string (args->v_expr.expression->v_list.name); + } + else + { + for (i = 0, args = args->v_expr.expression; args != NULL; args = args->v_list.next) + { + object->data[i] = _gst_intern_string (args->v_list.value->v_list.name); + i = i + 1; + } + } + + object = new_instance_with (_gst_array_class, tempCount, &tempsOOP); + INC_ADD_OOP (tempsOOP); + + for (i = 0, args = method->v_method.temporaries; args != NULL; args = args->v_list.next) + { + object->data[i] = _gst_intern_string (args->v_list.name); + i = i + 1; + } + + new_instance (_gst_debug_information_class, &debugInfo); + INC_ADD_OOP (debugInfo); + + inst_var_at_put (debugInfo, 1, argsOOP); + inst_var_at_put (debugInfo, 2, tempsOOP); + + inst_var_at_put (methodOOP, 3, debugInfo); + } } if (methodOOP != _gst_nil_oop) @@ -1064,9 +1106,13 @@ compile_block (tree_node blockExpr) bc_vector current_bytecodes, blockByteCodes; int argCount, tempCount; int stack_depth; - OOP blockClosureOOP, blockOOP; + int i; + OOP blockClosureOOP, blockOOP, argsOOP, tempsOOP; + OOP debugInfo; gst_compiled_block block; + gst_object object; inc_ptr incPtr; + tree_node args; current_bytecodes = _gst_save_bytecode_array (); @@ -1102,6 +1148,31 @@ compile_block (tree_node blockExpr) blockOOP = make_block (_gst_get_arg_count (), _gst_get_temp_count (), blockByteCodes, stack_depth); INC_ADD_OOP (blockOOP); + + object = new_instance_with (_gst_array_class, argCount, &argsOOP); + INC_ADD_OOP (argsOOP); + + for (i = 0, args = blockExpr->v_block.arguments; args != NULL; args = args->v_list.next) { + object->data[i] = _gst_intern_string (args->v_list.name); + i = i + 1; + } + + object = new_instance_with (_gst_array_class, tempCount, &tempsOOP); + INC_ADD_OOP (tempsOOP); + + for (i = 0, args = blockExpr->v_block.temporaries; args != NULL; args = args->v_list.next) { + object->data[i] = _gst_intern_string (args->v_list.name); + i = i + 1; + } + + new_instance (_gst_debug_information_class, &debugInfo); + INC_ADD_OOP (debugInfo); + + inst_var_at_put (debugInfo, 1, argsOOP); + inst_var_at_put (debugInfo, 2, tempsOOP); + + inst_var_at_put (blockOOP, 3, debugInfo); + _gst_pop_old_scope (); /* emit standard byte sequence to invoke a block: diff --git a/libgst/comp.h b/libgst/comp.h index 91a1f9c..56b4d44 100644 --- a/libgst/comp.h +++ b/libgst/comp.h @@ -136,6 +136,7 @@ typedef struct gst_compiled_method OBJ_HEADER; OOP literals; method_header header; + OOP debug; OOP descriptor; gst_uchar bytecodes[1]; } @@ -208,6 +209,7 @@ typedef struct gst_compiled_block OBJ_HEADER; OOP literals; block_header header; + OOP debug; OOP method; gst_uchar bytecodes[1]; } diff --git a/libgst/dict.c b/libgst/dict.c index f4324b7..b06c6ed 100644 --- a/libgst/dict.c +++ b/libgst/dict.c @@ -177,6 +177,7 @@ OOP _gst_weak_key_identity_dictionary_class = NULL; OOP _gst_weak_value_identity_dictionary_class = NULL; OOP _gst_write_stream_class = NULL; OOP _gst_processor_oop = NULL; +OOP _gst_debug_information_class = NULL; /* Called when a dictionary becomes full, this routine replaces the dictionary instance that DICTIONARYOOP is pointing to with a new, @@ -506,8 +507,8 @@ static const class_definition class_info[] = { "ByteArray", NULL, NULL, "CSymbols" }, {&_gst_compiled_code_class, &_gst_arrayed_collection_class, - GST_ISP_UCHAR, false, 2, - "CompiledCode", "literals header", + GST_ISP_UCHAR, false, 3, + "CompiledCode", "literals header debugInfo", NULL, NULL }, {&_gst_compiled_block_class, &_gst_compiled_code_class, @@ -747,7 +748,11 @@ static const class_definition class_info[] = { {&_gst_file_segment_class, &_gst_object_class, GST_ISP_FIXED, true, 3, - "FileSegment", "file startPos size", NULL, NULL } + "FileSegment", "file startPos size", NULL, NULL }, + + {&_gst_debug_information_class, &_gst_object_class, + GST_ISP_FIXED, true, 2, + "DebugInformation", "args temps", NULL, NULL } /* Classes not defined here (like Point/Rectangle/RunArray) are defined after the kernel has been fully initialized. */ diff --git a/libgst/dict.h b/libgst/dict.h index 93224c9..23c9408 100644 --- a/libgst/dict.h +++ b/libgst/dict.h @@ -447,6 +447,7 @@ extern OOP _gst_weak_key_identity_dictionary_class ATTRIBUTE_HIDDEN; extern OOP _gst_weak_value_identity_dictionary_class ATTRIBUTE_HIDDEN; extern OOP _gst_write_stream_class ATTRIBUTE_HIDDEN; extern OOP _gst_processor_oop ATTRIBUTE_HIDDEN; +extern OOP _gst_debug_information_class ATTRIBUTE_HIDDEN; /* The size of the indexed instance variables corresponding to the various instanceSpec values declared in gstpriv.h. */ diff --git a/libgst/files.c b/libgst/files.c index a7156f9..913ade1 100644 --- a/libgst/files.c +++ b/libgst/files.c @@ -290,6 +290,8 @@ static const char standard_files[] = { "PkgLoader.st\0" "DirPackage.st\0" "Autoload.st\0" + + "DebugInformation.st\0" }; /* The argc and argv that are passed to libgst via gst_smalltalk_args. diff --git a/packages.xml b/packages.xml index fc6a049..c3b6514 100644 --- a/packages.xml +++ b/packages.xml @@ -189,6 +189,7 @@ LinkedList.st Rectangle.st AnsiDates.st + DebugInformation.st CompildCode.st LookupKey.st BindingDict.st diff --git a/packages/stinst/parser/STCompiler.st b/packages/stinst/parser/STCompiler.st index 74fc9a8..981ca53 100644 --- a/packages/stinst/parser/STCompiler.st +++ b/packages/stinst/parser/STCompiler.st @@ -488,6 +488,7 @@ indexed'' bytecode. The resulting stream is ifTrue: [error := handler value: method value: ann. error notNil ifTrue: [self compileError: error]]]. + self createDebugInformationFor: method from: node. ^method ] @@ -543,6 +544,7 @@ indexed'' bytecode. The resulting stream is bytecodes: bc depth: self maxDepth literals: self literals. + self createDebugInformationFor: block from: aNode. self depthSet: depth. clean := block flags. clean == 0 @@ -994,6 +996,11 @@ indexed'' bytecode. The resulting stream is selector := selectorBuilder contents asSymbol. ^Message selector: selector arguments: arguments contents ] + + createDebugInformationFor: aCompiledCode from: aNode [ + aCompiledCode + debugInformation: (DebugInformation args: aNode argumentNames temps: aNode body temporaryNames). + ] ] diff --git a/tests/compiler.ok b/tests/compiler.ok index 5f1b74d..a797b97 100644 --- a/tests/compiler.ok +++ b/tests/compiler.ok @@ -148,3 +148,10 @@ Execution begins... 'abc' 'def' returned value is ReadStream new "<0>" + +Execution begins... +true +true +true +true +returned value is nil diff --git a/tests/compiler.st b/tests/compiler.st index 1fbdf57..461babb 100644 --- a/tests/compiler.st +++ b/tests/compiler.st @@ -362,3 +362,22 @@ Eval [ #((#{ABC})) ] "Check that lookahead tokens are not discarded after compiling a doit." Eval ['''abc'' printNl ''def'' printNl' readStream fileIn] + +"Test debug informations are generated" +Object subclass: Foo [ + a_1: i_1 a_2: i_2 [ + | i j k | + + ^ [ :a :b :c | | d e f | ] + ] +] + +Eval [ + | mth | + mth := Foo>>#'a_1:a_2:'. + (mth arguments = #(#'i_1' #'i_2')) printNl. + (mth temporaries = #(#'i' #'j' #'k')) printNl. + ((mth blockAt: 1) arguments = #(#'a' #'b' #'c')) printNl. + ((mth blockAt: 1) temporaries = #(#'d' #'e' #'f')) printNl. + nil +] diff --git a/tests/stcompiler.ok b/tests/stcompiler.ok index a0cebf4..4587736 100644 --- a/tests/stcompiler.ok +++ b/tests/stcompiler.ok @@ -60,3 +60,10 @@ Execution begins... true true returned value is true + +Execution begins... +true +true +true +true +returned value is nil diff --git a/tests/stcompiler.st b/tests/stcompiler.st index 5605a6e..0b38220 100644 --- a/tests/stcompiler.st +++ b/tests/stcompiler.st @@ -140,3 +140,23 @@ Eval [ (bla sharedPools = #('STInST') asOrderedCollection) printNl. (bla classVarNames = #('ClassInst') asOrderedCollection) printNl. ] + +"Test debug informations are generated" +Object subclass: Foo [ + a_1: i_1 a_2: i_2 [ + | i j k | + + ^ [ :a :b :c | | d e f | ] + ] +] + +Eval [ + | mth | + mth := Foo>>#'a_1:a_2:'. + (mth arguments = #(#'i_1' #'i_2')) printNl. + (mth temporaries = #(#'i' #'j' #'k')) printNl. + ((mth blockAt: 1) arguments = #(#'a' #'b' #'c')) printNl. + ((mth blockAt: 1) temporaries = #(#'d' #'e' #'f')) printNl. + nil +] + -- 1.8.1.2 >From 284f9f6bba940e39a6e12d36e307309a27b90aa9 Mon Sep 17 00:00:00 2001 From: Gwenael Casaccio Date: Mon, 27 May 2013 12:13:02 +0200 Subject: [PATCH 2/2] Use one array for the variables --- kernel/CompildCode.st | 6 ++++-- kernel/DebugInformation.st | 21 +++++++-------------- libgst/comp.c | 34 ++++++++++++++-------------------- libgst/dict.c | 4 ++-- packages/stinst/parser/STCompiler.st | 2 +- 5 files changed, 28 insertions(+), 39 deletions(-) diff --git a/kernel/CompildCode.st b/kernel/CompildCode.st index fcbfe1d..06eb0ad 100644 --- a/kernel/CompildCode.st +++ b/kernel/CompildCode.st @@ -317,7 +317,8 @@ superclass for blocks and methods'> arguments [ - ^ debugInfo arguments + self numArgs = 0 ifTrue: [ ^ #() ]. + ^ debugInfo variables copyFrom: 1 to: self numArgs ] numArgs [ @@ -330,7 +331,8 @@ superclass for blocks and methods'> temporaries [ - ^ debugInfo temporaries + self numTemps = 0 ifTrue: [ ^ #() ]. + ^ debugInfo variables copyFrom: self numArgs + 1 to: self numArgs + self numTemps ] numTemps [ diff --git a/kernel/DebugInformation.st b/kernel/DebugInformation.st index 5297164..4defe48 100644 --- a/kernel/DebugInformation.st +++ b/kernel/DebugInformation.st @@ -32,33 +32,26 @@ Object subclass: DebugInformation [ - DebugInformation class >> args: anArgsArray temps: aTempsArray [ + DebugInformation class >> variables: anArray [ ^ self new - args: anArgsArray temps: aTempsArray; + variables: anArray; yourself ] - | args temps | + | variables | - args: anArgsArray temps: aTempsArray [ + variables: anArray [ - args := anArgsArray. - temps := aTempsArray. + variables := anArray. ] - arguments [ + variables [ - ^ args - ] - - temporaries [ - - - ^ temps + ^ variables ] ] diff --git a/libgst/comp.c b/libgst/comp.c index ac830e4..99f75e9 100644 --- a/libgst/comp.c +++ b/libgst/comp.c @@ -693,7 +693,7 @@ _gst_compile_method (tree_node method, bc_vector bytecodes; int stack_depth; int i, argCount, tempCount; - OOP argsOOP, tempsOOP, debugInfo; + OOP variablesOOP, debugInfo; gst_object object; tree_node args; inc_ptr incPtr; @@ -833,28 +833,27 @@ _gst_compile_method (tree_node method, if (methodOOP != _gst_nil_oop) { - object = new_instance_with (_gst_array_class, argCount, &argsOOP); - INC_ADD_OOP (argsOOP); + object = new_instance_with (_gst_array_class, argCount + tempCount, &variablesOOP); + INC_ADD_OOP (variablesOOP); args = method->v_method.selectorExpr; + i = 0; if (args->nodeType == TREE_BINARY_EXPR) { - object->data[0] = _gst_intern_string (args->v_expr.expression->v_list.name); + object->data[i] = _gst_intern_string (args->v_expr.expression->v_list.name); + i = i + 1; } else { - for (i = 0, args = args->v_expr.expression; args != NULL; args = args->v_list.next) + for (args = args->v_expr.expression; args != NULL; args = args->v_list.next) { object->data[i] = _gst_intern_string (args->v_list.value->v_list.name); i = i + 1; } } - object = new_instance_with (_gst_array_class, tempCount, &tempsOOP); - INC_ADD_OOP (tempsOOP); - - for (i = 0, args = method->v_method.temporaries; args != NULL; args = args->v_list.next) + for (args = method->v_method.temporaries; args != NULL; args = args->v_list.next) { object->data[i] = _gst_intern_string (args->v_list.name); i = i + 1; @@ -863,8 +862,7 @@ _gst_compile_method (tree_node method, new_instance (_gst_debug_information_class, &debugInfo); INC_ADD_OOP (debugInfo); - inst_var_at_put (debugInfo, 1, argsOOP); - inst_var_at_put (debugInfo, 2, tempsOOP); + inst_var_at_put (debugInfo, 1, variablesOOP); inst_var_at_put (methodOOP, 3, debugInfo); } @@ -1107,7 +1105,7 @@ compile_block (tree_node blockExpr) int argCount, tempCount; int stack_depth; int i; - OOP blockClosureOOP, blockOOP, argsOOP, tempsOOP; + OOP blockClosureOOP, blockOOP, variablesOOP; OOP debugInfo; gst_compiled_block block; gst_object object; @@ -1149,18 +1147,15 @@ compile_block (tree_node blockExpr) blockByteCodes, stack_depth); INC_ADD_OOP (blockOOP); - object = new_instance_with (_gst_array_class, argCount, &argsOOP); - INC_ADD_OOP (argsOOP); + object = new_instance_with (_gst_array_class, argCount + tempCount, &variablesOOP); + INC_ADD_OOP (variablesOOP); for (i = 0, args = blockExpr->v_block.arguments; args != NULL; args = args->v_list.next) { object->data[i] = _gst_intern_string (args->v_list.name); i = i + 1; } - object = new_instance_with (_gst_array_class, tempCount, &tempsOOP); - INC_ADD_OOP (tempsOOP); - - for (i = 0, args = blockExpr->v_block.temporaries; args != NULL; args = args->v_list.next) { + for (args = blockExpr->v_block.temporaries; args != NULL; args = args->v_list.next) { object->data[i] = _gst_intern_string (args->v_list.name); i = i + 1; } @@ -1168,8 +1163,7 @@ compile_block (tree_node blockExpr) new_instance (_gst_debug_information_class, &debugInfo); INC_ADD_OOP (debugInfo); - inst_var_at_put (debugInfo, 1, argsOOP); - inst_var_at_put (debugInfo, 2, tempsOOP); + inst_var_at_put (debugInfo, 1, variablesOOP); inst_var_at_put (blockOOP, 3, debugInfo); diff --git a/libgst/dict.c b/libgst/dict.c index b06c6ed..2217cef 100644 --- a/libgst/dict.c +++ b/libgst/dict.c @@ -751,8 +751,8 @@ static const class_definition class_info[] = { "FileSegment", "file startPos size", NULL, NULL }, {&_gst_debug_information_class, &_gst_object_class, - GST_ISP_FIXED, true, 2, - "DebugInformation", "args temps", NULL, NULL } + GST_ISP_FIXED, true, 1, + "DebugInformation", "variables", NULL, NULL } /* Classes not defined here (like Point/Rectangle/RunArray) are defined after the kernel has been fully initialized. */ diff --git a/packages/stinst/parser/STCompiler.st b/packages/stinst/parser/STCompiler.st index 981ca53..6890614 100644 --- a/packages/stinst/parser/STCompiler.st +++ b/packages/stinst/parser/STCompiler.st @@ -999,7 +999,7 @@ indexed'' bytecode. The resulting stream is createDebugInformationFor: aCompiledCode from: aNode [ aCompiledCode - debugInformation: (DebugInformation args: aNode argumentNames temps: aNode body temporaryNames). + debugInformation: (DebugInformation variables: aNode argumentNames, aNode body temporaryNames). ] ] -- 1.8.1.2