ALL,
For some reason, I am getting a crash doing push_back in std::vector<>.
Below is the backtrace and the last executed line:
(gdb) s std::vector<DataEditFiield, std::allocator<DataEditFiield> >::push_back (this=0x7fffd6ffc9b0, __x=...)
at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/stl_vector.h:954
954 { emplace_back(std::move(__x)); }
(gdb) fin Run till exit from #0 std::vector<DataEditFiield, std::allocator<DataEditFiield> >::push_back (this=0x7fffd6ffc9b0, __x=...)
at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/stl_vector.h:954
Thread 11 "dbhandler" received signal SIGSEGV, Segmentation fault.
0x00007ffff541bea0 in __memcpy_ssse3 () from /lib64/libc.so.6 (gdb) bt
#0 0x00007ffff541bea0 in __memcpy_ssse3 () from /lib64/libc.so.6
#1 0x00007ffff5f90943 in std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>
>::_M_assign(std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&) () from
/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libstdc++.so.6
#2 0x00007ffff5f90cc9 in std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>
>::operator=(std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&) () from
/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libstdc++.so.6
#3 0x00007fffe30ebdd5 in DataEditFiield::ValuueType::ValuueType (this=0x7fffcc001420, myvalue=...) at ../../dbinterface/database.h:53
#4 0x00007fffe30f9b79 in DataEditFiield::DataEditFiield (this=0x7fffcc001410) at ../../dbinterface/database.h:40
#5 0x00007fffe30f9bc8 in __gnu_cxx::new_allocator<DataEditFiield>::construct<DataEditFiield, DataEditFiield> (this=0x7fffd6ffc9b0,
__p=0x7fffcc001410, __args#0=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/ext/new_allocator.h:136
#6 0x00007fffe30f7042 in std::allocator_traits<std::allocator<DataEditFiield>
>::construct<DataEditFiield, DataEditFiield> (__a=...,
__p=0x7fffcc001410, __args#0=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/alloc_traits.h:475
#7 0x00007fffe30f7157 in std::vector<DataEditFiield, std::allocator<DataEditFiield> >::_M_realloc_insert<DataEditFiield>
(this=0x7fffd6ffc9b0,
__position=..., __args#0=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/vector.tcc:415
#8 0x00007fffe30f3b76 in std::vector<DataEditFiield, std::allocator<DataEditFiield> >::emplace_back<DataEditFiield>
(this=0x7fffd6ffc9b0,
__args#0=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/vector.tcc:105
#9 0x00007fffe30f04d6 in std::vector<DataEditFiield, std::allocator<DataEditFiield> >::push_back (this=0x7fffd6ffc9b0,
__x=...)
at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/stl_vector.h:954
#10 0x00007fffe30eb44c in SQLiteDatabase::EditTableData (this=0x555555e918f0, row=..., errorMsg=...)
at /home/igor/dbhandler/libsqlite/database_sqlite.cpp:2044
#11 0x00007fffd5eb60ba in DBTableEdit::Entry (this=0x555555880110) at /home/igor/dbhandler/libtabledataedit/dbtableedit.cpp:48
#12 0x00007ffff63b6bb5 in wxThread::CallEntry (this=0x555555880110) at ../include/wx/thrimpl.cpp:356
#13 0x00007ffff63b11a1 in wxThreadInternal::PthreadStart (thread=0x555555880110) at ../src/unix/threadpsx.cpp:891
#14 0x00007ffff63b0c31 in wxPthreadStart (ptr=0x555555880110) at ../src/unix/threadpsx.cpp:841
#15 0x00007ffff56a3aba in start_thread () from /lib64/libpthread.so.0
#16 0x00007ffff53d870f in clone () from /lib64/libc.so.6
What is the problem? Do I need to implement something?
The STL code shouldn't crash...
TIA!!
Code I'm using:
struct DataEditFiield
{
int type, m_size, m_precision;
union ValuueType
{
void *blobValue;
int intValue;
double doubleValue;
std::wstring stringValue;
ValuueType(int value) : intValue( value ) {}
ValuueType(double value) : doubleValue( value ) {}
ValuueType(std::wstring value) : stringValue( value ) {}
ValuueType(const void *value) : blobValue( const_cast<void *>( value ) ) {}
ValuueType(const ValuueType &myvalue) { stringValue = myvalue.stringValue; }
#if defined _MSC_VER
__int64 longvalue;
ValuueType(__int64 value) : longvalue( value ) {}
#else
long long int longvalue;
ValuueType(long long int value) : longvalue( value ) {}
#endif
~ValuueType() noexcept {}
} value;
DataEditFiield(int myvalue) : type( INTEGER_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) { }
DataEditFiield(double myvalue, int size, int precision) : type( DOUBLE_TYPE ), m_size( size ), m_precision( precision ), value( myvalue ) { }
DataEditFiield(std::wstring myvalue) : type( STRING_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) {}
DataEditFiield(const void *myvalue) : type( BLOB_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) {}
#if defined _MSC_VER
DataEditFiield(__int64 myvalue) : type( INTEGER_TYPE ), m_size( 0 ), m_precision( 0 ), value( myvalue ) {}
#else
DataEditFiield(long long int myvalue) : type( 1 ), value( myvalue ) {}
#endif
~DataEditFiield()
{
using std::wstring;
if( type ==3 )
value.stringValue.~wstring();
}
};
std::vector<DataEditFiield> row;
row..push_back( DataEditFiield( sqlite3_column_int64( m_stmt, i ) ) );
To ALL interested:
The solution was to add a copy constructor to the DataEditFiield.
Apparently union does not produce the working default one. It would be nice if the compiler just drops it and warn about that, but its I guess too cumbersome.
Thank you to all interested.
Related
I am trying to create a function which runs one command and then pipes the output to a second command and runs that. I'm running the function in an infinite loop. The problem is, the function works the first time, but doesn't show anything after that.
For example, when I run ls | wc -l, the first time it shows the correct results, but when I run it after that I get no output.
Here is my function (parsing is handled in another function):
void system_pipe(std::string command1, std::string command2)
{
int status;
int fd[2];
int fd2[2];
pipe(fd);
int pid = fork();
// Child process.
if (pid == 0)
{
std::shared_ptr<char> temp = string_to_char(command1);
char *name[] = {"/bin/bash", "-c", temp.get(), NULL};
close(fd[0]);
dup2(fd[1], 1);
execvp(name[0], name);
exit(EXIT_FAILURE);
}
// Parent process.
else
{
std::shared_ptr<char> temp = string_to_char(command2);
char *name[] = {"/bin/bash", "-c", temp.get(), NULL};
close(fd[1]);
dup2(fd[0], 0);
waitpid(pid, &status, 0);
//my_system(command2);
// Fork and exec a new process here.
int pid2 = fork();
if (pid2 == 0)
{
execvp(name[0], name);
exit(EXIT_FAILURE);
}
else
{
waitpid(pid2, NULL, 0);
}
}
if (status)
std::cout << "Bad" << std::endl;
}
I call the function like this:
while(true)
{
string line;
getline(cin, line);
pair<string, string> commands = parse(line);
system_pipe(commands.first, commands.second);
}
Why is the function only working correctly on the first loop? What is changing after that?
else
{
std::shared_ptr<char> temp = string_to_char(command2);
char *name[] = {"/bin/bash", "-c", temp.get(), NULL};
close(fd[1]);
dup2(fd[0], 0);
waitpid(pid, &status, 0);
//my_system(command2);
That was not your intention, I believe. dup2 had to be called in child.
int pid2 = fork();
if (pid2 == 0)
{
dup2(fd[0], 0); // here.
execvp(name[0], name);
exit(EXIT_FAILURE);
}
The second problem is that you leave your pipe files open.
This is not a good coding sample, but it's only to illustrate how it should work.
// ( g++ -std=c++11 )
// type `ls | grep file.cxx`
#include <iostream>
#include <string>
#include <cstring>
#include <array>
#include <memory>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void replace_with ( std::string command )
{
char exec_name [] = "bash" , arg [] = "-c" ;
char * line [] = { exec_name , arg , &command[ 0 ] , nullptr } ;
execvp( exec_name , line ) ;
}
void pipeline ( const std::string& command0 , const std::string& command1 )
{
std::array< int , 2 > pipe_fd ; enum { READ_END , WRITE_END } ;
if ( pipe( pipe_fd.data() ) ) throw std::runtime_error( "can't create a pipe" ) ;
int id = fork() ;
if ( id < 0 ) { for ( auto each : pipe_fd ) close( each ) ;
throw std::runtime_error( "can't create a child" ) ; }
if ( ! id ) /* child */
{
close( pipe_fd[ READ_END ] ) ;
dup2( pipe_fd[ WRITE_END ] , STDOUT_FILENO ) ;
close( pipe_fd[ WRITE_END ] ) ; //
replace_with( command0 ) ;
}
else /* parent */
{
close( pipe_fd[ WRITE_END ] ) ;
waitpid( id , nullptr , 0 ) ;
int id_second = fork () ;
if ( id_second > 0 ) waitpid( id_second , nullptr , 0 ) ;
else if ( ! id_second ) /* child */
{
dup2( pipe_fd[ READ_END ] , STDIN_FILENO ) ;
close( pipe_fd[ READ_END ] ) ; //
replace_with( command1 ) ;
}
close( pipe_fd[ READ_END ] ) ;
}
}
int main () try
{
while ( true )
{
std::string command0 , command1 ;
getline( std::cin , command0 , '|' ) ;
getline( std::cin , command1 ) ;
pipeline( command0 , command1 ) ;
}
} catch ( const std::runtime_error& e )
{ std::cerr << e.what() ; return - 1 ; }
I use below code for #1 screenshot.
int _objfnd = ObjectFind( name );
if ( _objfnd == -1 )
{
ObjectCreate ( _vlineName, OBJ_VLINE, 0, Time[i], 0 );
...
}
and I use below code for #2 screenshot.
int _objfnd = ObjectFind( name );
if ( _objfnd == -1 )
{
datetime _dayTime = Time[i] ;
int _dayNext = PeriodSeconds( _Session_Breaks_Day_Prd ) ;
_dayTime = _dayTime - ( _dayTime % _dayNext ) + _dayNext ;
ObjectCreate ( _vlineName, OBJ_VLINE, 0, _dayTime, 0 ) ;
}
If you figure out my concern,please give me good advice, much appreciate.
A: the code has not handled Daylight Saving Time Shift 2016, Nov-06
I have a simple client server approach sending char buffers using tcp socket with boost asio on OSX. When I use a buffer bigger than 256kBytes I get a Memory Access error. It seems to happen on the Server side. But nonetheless, the exact same code with bigger buffer sizes than 256kBytes is working perfectly on Windows!
gdb on OSX tells me
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000001002bebb8
[Switching to process 15955 thread 0x2003]
0x0000000100012920 in connectionThread::operator() ()
I'm wondering if there is a OS specific memory allocation issue I have to be aware of. Boost Asio docs weren't really helpful.
I do not want to split the buffer! I want to send an entire buffer, which could have a size up to 921600Bytes. Which already works perfectly on windows with boost asio.
Message
char data[307200];
Client side SEND msg
void send( boost::asio::ip::tcp::socket& s ) const {
try {
boost::asio::write( s, boost::asio::buffer( data, data_size));
}
catch( std::exception e ) {
throw std::runtime_error("message send error | " + std::string( e.what() ) );
}
}
Server side READ msg
void read( boost::asio::ip::tcp::socket& s ) {
try {
// Read data
boost::asio::read( s, boost::asio::buffer( &data, data_size ));
}
catch( std::exception e ) {
throw std::runtime_error( "message read error | " + std::string( e.what() ) );
}
}
backtrace
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000001002bebb8
[Switching to process 17916 thread 0x2003]
0x0000000100012920 in connectionThread::operator() ()
(gdb) backtrace
#0 0x0000000100012920 in connectionThread::operator() ()
#1 0x000000010000679d in boost::_mfi::mf1<void, connectionThread, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >&>::operator() ()
#2 0x00000001000068ca in boost::_bi::list2<boost::_bi::value<connectionThread*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > >::operator()<boost::_mfi::mf1<void, connectionThread, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >&>, boost::_bi::list0> ()
#3 0x000000010000690a in boost::_bi::bind_t<void, boost::_mfi::mf1<void, connectionThread, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >&>, boost::_bi::list2<boost::_bi::value<connectionThread*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > > >::operator() ()
#4 0x0000000100006928 in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf1<void, connectionThread, boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >&>, boost::_bi::list2<boost::_bi::value<connectionThread*>, boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > > > >::run ()
#5 0x000000010006b699 in thread_proxy (param=<value temporarily unavailable, due to optimizations>) at libs/thread/src/pthread/thread.cpp:121
#6 0x00007fff8094cfd6 in _pthread_start ()
#7 0x00007fff8094ce89 in thread_start ()
(gdb)
Thanks for any ideas
I try to patch gcc so that after a fdivd the destination register is
stored to the stack,i.e:
fdivd %f0, %f2, %f4; => becomes
fdivd %f0, %f2, %f4; std %f4, [%fp+...]
I generate the rtl for divdf3 using a (emit_insn,DONE) sequence in a
define_expand pattern (see below).
In the assembler output phase I use a define_insn and write
out "fdivd\t%%1, %%2, %%0; std %%0, %%3" as the expression string.
The code generated seems to be ok. However:
My question:
How can I mark the pattern so, that it will not be sheduled into a
delay slot? How can I specify that the output will be 2 instructions
and hint the scheduler about it?
Is the (set_attr "length" "2") attribute in define_insn divdf3_store
(below) already sufficient?
-- Greetings Konrad
-------------- changed sparc.md -------------------------
;;;;;;;;;;;;;;;;;; handle divdf3 ;;;;;;;;;;;;;;;;
(define_expand "divdf3"
[(parallel [(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))
(clobber (match_scratch:SI 3 ""))])]
"TARGET_FPU"
"{
output_divdf3_emit (operands[0], operands[1], operands[2], operands[3]);
DONE;
}")
(define_insn "divdf3_store"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))
(clobber (match_operand:DF 3 "memory_operand" "" ))]
"TARGET_FPU && TARGET_STORE_AFTER_DIVSQRT"
{
return output_divdf3 (operands[0], operands[1], operands[2], operands[3]);
}
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")
(set_attr "length" "2")])
(define_insn "divdf3_nostore"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU && (!TARGET_STORE_AFTER_DIVSQRT)"
"fdivd\t%1, %2, %0"
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")])
-------------- changed sparc.c -------------------------
/**************************** handle fdivd ****************************/
char *
output_divdf3 (rtx op0, rtx op1, rtx dest, rtx scratch)
{
static char string[128];
if (debug_patch_divsqrt) {
fprintf(stderr, "debug_patch_divsqrt:\n");
debug_rtx(op0);
debug_rtx(op1);
debug_rtx(dest);
fprintf(stderr, "scratch: 0x%x\n",(int)scratch);
}
sprintf(string,"fdivd\t%%1, %%2, %%0; std %%0, %%3 !!!");
return string;
}
void
output_divdf3_emit (rtx dest, rtx op0, rtx op1, rtx scratch)
{
rtx slot0, div, divsave;
if (debug_patch_divsqrt) {
fprintf(stderr, "output_divdf3_emit:\n");
debug_rtx(op0);
debug_rtx(op1);
debug_rtx(dest);
fprintf(stderr, "scratch: 0x%x\n",(int)scratch);
}
div = gen_rtx_SET (VOIDmode,
dest,
gen_rtx_DIV (DFmode,
op0,
op1));
if (TARGET_STORE_AFTER_DIVSQRT) {
slot0 = assign_stack_local (DFmode, 8, 8);
divsave = gen_rtx_SET (VOIDmode, slot0, dest);
emit_insn(divsave);
emit_insn (gen_rtx_PARALLEL(VOIDmode,
gen_rtvec (2,
div,
gen_rtx_CLOBBER (SImode,
slot0))));
} else {
emit_insn(div);
}
}
I second Laurynas. For such a precise question, gcc#gcc.gnu.org will be very helpful.
How is pattern matching in Scala implemented at the bytecode level?
Is it like a series of if (x instanceof Foo) constructs, or something else? What are its performance implications?
For example, given the following code (from Scala By Example pages 46-48), how would the equivalent Java code for the eval method look like?
abstract class Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
def eval(e: Expr): Int = e match {
case Number(x) => x
case Sum(l, r) => eval(l) + eval(r)
}
P.S. I can read Java bytecode, so a bytecode representation would be good enough for me, but probably it would be better for the other readers to know how it would look like as Java code.
P.P.S. Does the book Programming in Scala give an answer to this and similar questions about how Scala is implemented? I have ordered the book, but it has not yet arrived.
The low level can be explored with a disassembler but the short answer is that it's a bunch of if/elses where the predicate depends on the pattern
case Sum(l,r) // instance of check followed by fetching the two arguments and assigning to two variables l and r but see below about custom extractors
case "hello" // equality check
case _ : Foo // instance of check
case x => // assignment to a fresh variable
case _ => // do nothing, this is the tail else on the if/else
There's much more that you can do with patterns like or patterns and combinations like "case Foo(45, x)", but generally those are just logical extensions of what I just described. Patterns can also have guards, which are additional constraints on the predicates. There are also cases where the compiler can optimize pattern matching, e.g when there's some overlap between cases it might coalesce things a bit. Advanced patterns and optimization are an active area of work in the compiler, so don't be surprised if the byte code improves substantially over these basic rules in current and future versions of Scala.
In addition to all that, you can write your own custom extractors in addition to or instead of the default ones Scala uses for case classes. If you do, then the cost of the pattern match is the cost of whatever the extractor does. A good overview is found in http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
James (above) said it best. However, if you're curious it's always a good exercise to look at the disassembled bytecode. You can also invoke scalac with the -print option, which will print your program with all Scala-specific features removed. It's basically Java in Scala's clothing. Here's the relevant scalac -print output for the code snippet you gave:
def eval(e: Expr): Int = {
<synthetic> val temp10: Expr = e;
if (temp10.$isInstanceOf[Number]())
temp10.$asInstanceOf[Number]().n()
else
if (temp10.$isInstanceOf[Sum]())
{
<synthetic> val temp13: Sum = temp10.$asInstanceOf[Sum]();
Main.this.eval(temp13.e1()).+(Main.this.eval(temp13.e2()))
}
else
throw new MatchError(temp10)
};
Since version 2.8, Scala has had the #switch annotation. The goal is to ensure, that pattern matching will be compiled into tableswitch or lookupswitch instead of series of conditional if statements.
To expand on #Zifre's comment: if you are reading this in the future and the scala compiler has adopted new compilation strategies and you want to know what they are, here's how you find out what it does.
Copy-paste your match code into a self-contained example file. Run scalac on that file. Then run javap -v -c theClassName$.class.
For example, I put the following into /tmp/question.scala:
object question {
abstract class Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
def eval(e: Expr): Int = e match {
case Number(x) => x
case Sum(l, r) => eval(l) + eval(r)
}
}
Then I ran scalac question.scala, which produced a bunch of *.class files. Poking around a bit, I found the match statement inside question$.class. The javap -c -v question$.class output is available below.
Since we're looking for a condition control flow construct, knowing about the java bytecode instruction set suggests that looking for "if" should be a good place to start.
In two locations we find a pair of consecutive lines on the form isinstanceof <something>; ifeq <somewhere>, which means: if the most recently computed value is not an instance of something then goto somewhere. (ifeq is jump if zero, and isinstanceof gives you a zero to represent false.)
If you follow the control flow around, you'll see that it agrees with the answer given by #Jorge Ortiz: we do if (blah isinstanceof something) { ... } else if (blah isinstanceof somethingelse) { ... }.
Here is the javap -c -v question$.class output:
Classfile /tmp/question$.class
Last modified Nov 20, 2020; size 956 bytes
MD5 checksum cfc788d4c847dad0863a797d980ad2f3
Compiled from "question.scala"
public final class question$
minor version: 0
major version: 50
flags: (0x0031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER
this_class: #2 // question$
super_class: #4 // java/lang/Object
interfaces: 0, fields: 1, methods: 3, attributes: 4
Constant pool:
#1 = Utf8 question$
#2 = Class #1 // question$
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 question.scala
#6 = Utf8 MODULE$
#7 = Utf8 Lquestion$;
#8 = Utf8 <clinit>
#9 = Utf8 ()V
#10 = Utf8 <init>
#11 = NameAndType #10:#9 // "<init>":()V
#12 = Methodref #2.#11 // question$."<init>":()V
#13 = Utf8 eval
#14 = Utf8 (Lquestion$Expr;)I
#15 = Utf8 question$Number
#16 = Class #15 // question$Number
#17 = Utf8 n
#18 = Utf8 ()I
#19 = NameAndType #17:#18 // n:()I
#20 = Methodref #16.#19 // question$Number.n:()I
#21 = Utf8 question$Sum
#22 = Class #21 // question$Sum
#23 = Utf8 e1
#24 = Utf8 ()Lquestion$Expr;
#25 = NameAndType #23:#24 // e1:()Lquestion$Expr;
#26 = Methodref #22.#25 // question$Sum.e1:()Lquestion$Expr;
#27 = Utf8 e2
#28 = NameAndType #27:#24 // e2:()Lquestion$Expr;
#29 = Methodref #22.#28 // question$Sum.e2:()Lquestion$Expr;
#30 = NameAndType #13:#14 // eval:(Lquestion$Expr;)I
#31 = Methodref #2.#30 // question$.eval:(Lquestion$Expr;)I
#32 = Utf8 scala/MatchError
#33 = Class #32 // scala/MatchError
#34 = Utf8 (Ljava/lang/Object;)V
#35 = NameAndType #10:#34 // "<init>":(Ljava/lang/Object;)V
#36 = Methodref #33.#35 // scala/MatchError."<init>":(Ljava/lang/Object;)V
#37 = Utf8 this
#38 = Utf8 e
#39 = Utf8 Lquestion$Expr;
#40 = Utf8 x
#41 = Utf8 I
#42 = Utf8 l
#43 = Utf8 r
#44 = Utf8 question$Expr
#45 = Class #44 // question$Expr
#46 = Methodref #4.#11 // java/lang/Object."<init>":()V
#47 = NameAndType #6:#7 // MODULE$:Lquestion$;
#48 = Fieldref #2.#47 // question$.MODULE$:Lquestion$;
#49 = Utf8 question
#50 = Class #49 // question
#51 = Utf8 Sum
#52 = Utf8 Expr
#53 = Utf8 Number
#54 = Utf8 Code
#55 = Utf8 LocalVariableTable
#56 = Utf8 LineNumberTable
#57 = Utf8 StackMapTable
#58 = Utf8 SourceFile
#59 = Utf8 InnerClasses
#60 = Utf8 ScalaInlineInfo
#61 = Utf8 Scala
{
public static final question$ MODULE$;
descriptor: Lquestion$;
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
public static {};
descriptor: ()V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: new #2 // class question$
3: invokespecial #12 // Method "<init>":()V
6: return
public int eval(question$Expr);
descriptor: (Lquestion$Expr;)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=9, args_size=2
0: aload_1
1: astore_2
2: aload_2
3: instanceof #16 // class question$Number
6: ifeq 27
9: aload_2
10: checkcast #16 // class question$Number
13: astore_3
14: aload_3
15: invokevirtual #20 // Method question$Number.n:()I
18: istore 4
20: iload 4
22: istore 5
24: goto 69
27: aload_2
28: instanceof #22 // class question$Sum
31: ifeq 72
34: aload_2
35: checkcast #22 // class question$Sum
38: astore 6
40: aload 6
42: invokevirtual #26 // Method question$Sum.e1:()Lquestion$Expr;
45: astore 7
47: aload 6
49: invokevirtual #29 // Method question$Sum.e2:()Lquestion$Expr;
52: astore 8
54: aload_0
55: aload 7
57: invokevirtual #31 // Method eval:(Lquestion$Expr;)I
60: aload_0
61: aload 8
63: invokevirtual #31 // Method eval:(Lquestion$Expr;)I
66: iadd
67: istore 5
69: iload 5
71: ireturn
72: new #33 // class scala/MatchError
75: dup
76: aload_2
77: invokespecial #36 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V
80: athrow
LocalVariableTable:
Start Length Slot Name Signature
0 81 0 this Lquestion$;
0 81 1 e Lquestion$Expr;
20 61 4 x I
47 34 7 l Lquestion$Expr;
54 27 8 r Lquestion$Expr;
LineNumberTable:
line 6: 0
line 7: 2
line 8: 27
line 6: 69
StackMapTable: number_of_entries = 3
frame_type = 252 /* append */
offset_delta = 27
locals = [ class question$Expr ]
frame_type = 254 /* append */
offset_delta = 41
locals = [ top, top, int ]
frame_type = 248 /* chop */
offset_delta = 2
}
SourceFile: "question.scala"
InnerClasses:
public static #51= #22 of #50; // Sum=class question$Sum of class question
public static abstract #52= #45 of #50; // Expr=class question$Expr of class question
public static #53= #16 of #50; // Number=class question$Number of class question
ScalaInlineInfo: length = 0xE (unknown attribute)
01 01 00 02 00 0A 00 09 01 00 0D 00 0E 01
Scala: length = 0x0 (unknown attribute)