Some tricks I found when dealing with V8 giant code base

Macros, macros every where Link to heading

  • Having problem understanding v8 macros?
    • Add this where ever you want
      static const int IAmHere = 1;
      
    • And run
      g++ -g -Wall -I.  -Iinclude -I... header.h   -E -D DEBUG > header.h.o
      
    • Search for IAmHere in header.h.o file generated
    • Have fun
  • To be continued

The do while (false) macro Link to heading

#define ASSEMBLE_BINOP(asm_instr)                                \
  do {                                                           \
    if (HasAddressingMode(instr)) {                              \
      size_t index = 1;                                          \
      Operand right = i.MemoryOperand(&index);                   \
      __ asm_instr(i.InputRegister(0), right);                   \
    } else {                                                     \
      if (HasImmediateInput(instr, 1)) {                         \
        if (HasRegisterInput(instr, 0)) {                        \
          __ asm_instr(i.InputRegister(0), i.InputImmediate(1)); \
        } else {                                                 \
          __ asm_instr(i.InputOperand(0), i.InputImmediate(1));  \
        }                                                        \
      } else {                                                   \
        if (HasRegisterInput(instr, 1)) {                        \
          __ asm_instr(i.InputRegister(0), i.InputRegister(1));  \
        } else {                                                 \
          __ asm_instr(i.InputRegister(0), i.InputOperand(1));   \
        }                                                        \
      }                                                          \
    }                                                            \
  } while (false)

Why do why (false) ? Because if we define:

#define WAKE_UP() makeCoffee(); drinkCoffee();

and use:

if (morning) WAKE_UP();

The intent is to execute both statements if morning is true. But it expands to:

if (morning) makeCoffee(); drinkCoffee();;
//                         ^             ^

Oops! We god a syntax error at the end. And if we remove that ; we still end up with the second statments still be executed.
If we wrap the 2 statements in side a block:

#define WAKE_UP() { makeCoffee(); drinkCoffee(); }

This is better, but still risk:

if (morning)
  WAKE_UP();
else
  sleepIn();

Now we get a compile error:

if (morning)
  { makeCoffee(); drinkCoffee(); };
//                                ^
else
  sleepIn();

Using do while (false) loop in macro looks funny. But it helps containing multiple statements in a block and also permits a semicolon at the end.

What does V8 do? Link to heading

d8 --print-op-code --code-comments --trace-hydrogen debug.js

trace-hydrogen writes itnermediate representation (IR) into hydrogen.cfg and can be viewed by C1Visualizer.

Change d8 build flags and rebuild Link to heading

To quickly update build flags and rebuild.

cd out/arm64.debug # or similar directory
gn gen . --args='is_component_build = true
is_debug = true
symbol_level = 2
target_cpu = "arm64"
v8_target_cpu = "arm64"
use_goma = false
v8_enable_backtrace = true
v8_enable_fast_mksnapshot = true
v8_enable_slow_dchecks = true
v8_optimized_debug = false
v8_enable_ignition_dispatch_counting = true'

autoninja -C .

.lldbinit Link to heading

## add following utils for lldb
## - job: Print a v8 heap object
## - jlh: Print v8::Local handle value
## - jco: Print the code object at the given pc (default: current pc)
## - jtt: Print the transition tree of a v8 Map
## - jst: Print the current JavaScript stack trace
## - jss: Skip the jitted stack on x64 to where we entered JS last
## - bta: Print stack trace with assertion scopes
## - setup_source_map_for_relative_paths: Set up a source map to point to V8's root
command script import ../../tools/lldb_commands.py

v8::internal::Script Link to heading

(lldb) call (void) _v8_internal_Print_Object(*((v8::internal::Script**)(script).location_))
0x3e5900210d01: [Script] in OldSpace
 - map: 0x3e59000062bd <Map[64]>
 - source: 0x3e59000c5855 <String[20]: "'Hello' + ', World!'">
 - name: 0x3e59000023e9 <undefined>
 - source_url: 0x3e59000023e9 <undefined>
 - line_offset: 0
 - column_offset: 0
 - type: 2
 - id: 3
 - context data: 0x3e59000023e9 <undefined>
 - compilation type: 0
 - line ends: 0x3e59000023e9 <undefined>
 - eval from position: 0
 - shared function infos: 0x3e5900003565 <Other heap object (WEAK_FIXED_ARRAY_TYPE)>

class delete method Link to heading

class AstStringConstants final {
public:
  AstStringConstants(Isolate* isolate, uint64_t hash_seed);
  AstStringConstants(const AstStringConstants&) = delete;
  AstStringConstants& operator=(const AstStringConstants&) = delete;

};

int main() {
	AstStringConstants * a = new AstStringConstants();
	
	// line 7 -> error: use of deleted function
	AstStringConstants * a2 = new AstStringConstants(*a);
	
	// line 8 -> error: use of deleted function
	AstStringConstants * a3 = new AstStringConstants();
	*a3 = *a;
	
	return 0;