github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/v8/lib/instruction_counter.cc (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see
    17  // <http://www.gnu.org/licenses/>.
    18  //
    19  
    20  #include "instruction_counter.h"
    21  #include "logger.h"
    22  
    23  static char sInstructionCounter[] = "_instruction_counter";
    24  
    25  static InstructionCounterIncrListener sListener = NULL;
    26  
    27  void NewInstructionCounterInstance(Isolate *isolate, Local<Context> context,
    28                                     size_t *counter, void *listenerContext) {
    29    Local<ObjectTemplate> counterTpl = ObjectTemplate::New(isolate);
    30    counterTpl->SetInternalFieldCount(2);
    31  
    32    counterTpl->Set(String::NewFromUtf8(isolate, "incr"),
    33                    FunctionTemplate::New(isolate, IncrCounterCallback),
    34                    static_cast<PropertyAttribute>(PropertyAttribute::DontDelete |
    35                                                   PropertyAttribute::ReadOnly));
    36  
    37    counterTpl->SetAccessor(
    38        String::NewFromUtf8(isolate, "count"), CountGetterCallback, 0,
    39        Local<Value>(), DEFAULT,
    40        static_cast<PropertyAttribute>(PropertyAttribute::DontDelete |
    41                                       PropertyAttribute::ReadOnly));
    42  
    43    Local<Object> instance = counterTpl->NewInstance(context).ToLocalChecked();
    44    instance->SetInternalField(0, External::New(isolate, counter));
    45    instance->SetInternalField(1, External::New(isolate, listenerContext));
    46  
    47    context->Global()->DefineOwnProperty(
    48        context, String::NewFromUtf8(isolate, sInstructionCounter), instance,
    49        static_cast<PropertyAttribute>(PropertyAttribute::DontDelete |
    50                                       PropertyAttribute::ReadOnly));
    51  }
    52  
    53  void IncrCounterCallback(const FunctionCallbackInfo<Value> &info) {
    54    Isolate *isolate = info.GetIsolate();
    55    Local<Object> thisArg = info.Holder();
    56    Local<External> count = Local<External>::Cast(thisArg->GetInternalField(0));
    57    Local<External> listenerContext =
    58        Local<External>::Cast(thisArg->GetInternalField(1));
    59  
    60    if (info.Length() < 1) {
    61      isolate->ThrowException(
    62          Exception::Error(String::NewFromUtf8(isolate, "incr: mssing params")));
    63      return;
    64    }
    65  
    66    Local<Value> arg = info[0];
    67    if (!arg->IsNumber()) {
    68      isolate->ThrowException(Exception::Error(
    69          String::NewFromUtf8(isolate, "incr: value must be number")));
    70      return;
    71    }
    72  
    73    // always return true.
    74    info.GetReturnValue().Set(true);
    75  
    76    int32_t val = arg->Int32Value();
    77    if (val < 0) {
    78      return;
    79    }
    80  
    81    size_t *cnt = static_cast<size_t *>(count->Value());
    82    *cnt += val;
    83  
    84    if (sListener != NULL) {
    85      sListener(isolate, *cnt, listenerContext->Value());
    86    }
    87  }
    88  
    89  void CountGetterCallback(Local<String> property,
    90                           const PropertyCallbackInfo<Value> &info) {
    91    Isolate *isolate = info.GetIsolate();
    92    Local<Object> thisArg = info.Holder();
    93    Local<External> count = Local<External>::Cast(thisArg->GetInternalField(0));
    94  
    95    size_t *cnt = static_cast<size_t *>(count->Value());
    96    info.GetReturnValue().Set(Number::New(isolate, (double)*cnt));
    97  }
    98  
    99  void IncrCounter(Isolate *isolate, Local<Context> context, size_t val) {
   100    if (val == 0) {
   101      return;
   102    }
   103  
   104    Local<Object> global = context->Global();
   105    HandleScope handle_scope(isolate);
   106  
   107    Local<Object> counter = Local<Object>::Cast(
   108        global->Get(String::NewFromUtf8(isolate, sInstructionCounter)));
   109  
   110    Local<External> count = Local<External>::Cast(counter->GetInternalField(0));
   111    Local<External> listenerContext =
   112        Local<External>::Cast(counter->GetInternalField(1));
   113  
   114    size_t *cnt = static_cast<size_t *>(count->Value());
   115    *cnt += val;
   116  
   117    if (sListener != NULL) {
   118      sListener(isolate, *cnt, listenerContext->Value());
   119    }
   120  }
   121  
   122  void SetInstructionCounterIncrListener(
   123      InstructionCounterIncrListener listener) {
   124    sListener = listener;
   125  }