Revision: 9500
Author:   [email protected]
Date:     Fri Sep 30 06:27:38 2011
Log: Revert "Support for precise stepping in functions compiled before debugging was started (step 2)"

This reverts commits r9499, r9497 and r9489.

Then changed caused a number of failures.

[email protected]

BUG=
TEST=

Review URL: http://codereview.chromium.org//8086020
http://code.google.com/p/v8/source/detail?r=9500

Deleted:
 /branches/bleeding_edge/test/mjsunit/debug-step-3.js
Modified:
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/compiler.h
 /branches/bleeding_edge/src/debug.cc
 /branches/bleeding_edge/src/debug.h
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/list-inl.h
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/utils.h

=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-step-3.js Fri Sep 30 01:39:56 2011
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --expose-debug-as debug
-
-// This test tests that full code compiled without debug break slots
-// is recompiled with debug break slots when debugging is started.
-
-// Get the Debug object exposed from the debug context global object.
-Debug = debug.Debug
-
-var bp;
-var done = false;
-var step_count = 0;
-var set_bp = false
-
-// Debug event listener which steps until the global variable done is true.
-function listener(event, exec_state, event_data, data) {
-  if (event == Debug.DebugEvent.Break) {
-    if (!done) exec_state.prepareStep(Debug.StepAction.StepNext);
-    step_count++;
-  }
-};
-
-// Set the global variables state to prpare the stepping test.
-function prepare_step_test() {
-  done = false;
-  step_count = 0;
-}
-
-// Test function to step through.
-function f() {
-  var a = 0;
-  if (set_bp) { bp = Debug.setBreakPoint(f, 3); }
-  var i = 1;
-  var j = 2;
-  done = true;
-};
-
-prepare_step_test();
-f();
-
-// Add the debug event listener.
-Debug.setListener(listener);
-
-// Make f set a breakpoint with an activation on the stack.
-prepare_step_test();
-set_bp = true;
-f();
-assertEquals(4, step_count);
-Debug.clearBreakPoint(bp);
-
-// Set a breakpoint on the first var statement (line 1).
-set_bp = false;
-bp = Debug.setBreakPoint(f, 3);
-
-// Step through the function ensuring that the var statements are hit as well.
-prepare_step_test();
-f();
-assertEquals(4, step_count);
-
-// Clear the breakpoint and check that no stepping happens.
-Debug.clearBreakPoint(bp);
-prepare_step_test();
-f();
-assertEquals(0, step_count);
-
-// Get rid of the debug event listener.
-Debug.setListener(null);
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Fri Sep 30 01:39:56 2011
+++ /branches/bleeding_edge/src/compiler.cc     Fri Sep 30 06:27:38 2011
@@ -58,6 +58,7 @@
       script_(script),
       extension_(NULL),
       pre_parse_data_(NULL),
+      supports_deoptimization_(false),
       osr_ast_id_(AstNode::kNoNumber) {
   Initialize(NONOPT);
 }
@@ -72,6 +73,7 @@
       script_(Handle<Script>(Script::cast(shared_info->script()))),
       extension_(NULL),
       pre_parse_data_(NULL),
+      supports_deoptimization_(false),
       osr_ast_id_(AstNode::kNoNumber) {
   Initialize(BASE);
 }
@@ -87,6 +89,7 @@
       script_(Handle<Script>(Script::cast(shared_info_->script()))),
       extension_(NULL),
       pre_parse_data_(NULL),
+      supports_deoptimization_(false),
       osr_ast_id_(AstNode::kNoNumber) {
   Initialize(BASE);
 }
@@ -305,9 +308,9 @@


 static bool GenerateCode(CompilationInfo* info) {
-  return info->IsCompilingForDebugging() || !V8::UseCrankshaft() ?
-      FullCodeGenerator::MakeCode(info) :
-      MakeCrankshaftCode(info);
+  return V8::UseCrankshaft() ?
+    MakeCrankshaftCode(info) :
+    FullCodeGenerator::MakeCode(info);
 }


=======================================
--- /branches/bleeding_edge/src/compiler.h      Fri Sep 30 01:39:56 2011
+++ /branches/bleeding_edge/src/compiler.h      Fri Sep 30 06:27:38 2011
@@ -120,19 +120,6 @@
     ASSERT(IsOptimizing());
     osr_ast_id_ = osr_ast_id;
   }
-  void MarkCompilingForDebugging(Handle<Code> current_code) {
-    ASSERT(mode_ != OPTIMIZE);
-    ASSERT(current_code->kind() == Code::FUNCTION);
-    flags_ |= IsCompilingForDebugging::encode(true);
-    if (current_code->is_compiled_optimizable()) {
-      EnableDeoptimizationSupport();
-    } else {
-      mode_ = CompilationInfo::NONOPT;
-    }
-  }
-  bool IsCompilingForDebugging() {
-    return IsCompilingForDebugging::decode(flags_);
-  }

   bool has_global_object() const {
return !closure().is_null() && (closure()->context()->global() != NULL);
@@ -152,12 +139,10 @@
   void DisableOptimization();

   // Deoptimization support.
-  bool HasDeoptimizationSupport() const {
-    return SupportsDeoptimization::decode(flags_);
-  }
+ bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
   void EnableDeoptimizationSupport() {
     ASSERT(IsOptimizable());
-    flags_ |= SupportsDeoptimization::encode(true);
+    supports_deoptimization_ = true;
   }

   // Determine whether or not we can adaptively optimize.
@@ -218,11 +203,6 @@
   class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
   // Is this a function from our natives.
   class IsNative: public BitField<bool, 6, 1> {};
-  // Is this code being compiled with support for deoptimization..
-  class SupportsDeoptimization: public BitField<bool, 7, 1> {};
-  // If compiling for debugging produce just full code matching the
-  // initial mode setting.
-  class IsCompilingForDebugging: public BitField<bool, 8, 1> {};


   unsigned flags_;
@@ -251,6 +231,7 @@

   // Compilation mode flag and whether deoptimization is allowed.
   Mode mode_;
+  bool supports_deoptimization_;
   int osr_ast_id_;

   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
=======================================
--- /branches/bleeding_edge/src/debug.cc        Fri Sep 30 06:06:31 2011
+++ /branches/bleeding_edge/src/debug.cc        Fri Sep 30 06:27:38 2011
@@ -1725,43 +1725,6 @@
   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
   thread_local_.last_fp_ = 0;
 }
-
-
-// Helper function to compile full code for debugging. This code will
-// have debug break slots and deoptimization
-// information. Deoptimization information is required in case that an
-// optimized version of this function is still activated on the
-// stack. It will also make sure that the full code is compiled with
-// the same flags as the previous version - that is flags which can
-// change the code generated. The current method of mapping from
-// already compiled full code without debug break slots to full code
-// with debug break slots depends on the generated code is otherwise
-// exactly the same.
-static bool CompileFullCodeForDebugging(Handle<SharedFunctionInfo> shared,
-                                        Handle<Code> current_code) {
-  ASSERT(!current_code->has_debug_break_slots());
-
-  CompilationInfo info(shared);
-  info.MarkCompilingForDebugging(current_code);
-  ASSERT(!info.shared_info()->is_compiled());
-  ASSERT(!info.isolate()->has_pending_exception());
-
-  // Use compile lazy which will end up compiling the full code in the
-  // configuration configured above.
-  bool result = Compiler::CompileLazy(&info);
-  ASSERT(result != Isolate::Current()->has_pending_exception());
-  info.isolate()->clear_pending_exception();
-#if DEBUG
-  if (result) {
-    Handle<Code> new_code(shared->code());
-    ASSERT(new_code->has_debug_break_slots());
-    ASSERT(current_code->is_compiled_optimizable() ==
-           new_code->is_compiled_optimizable());
- ASSERT(current_code->instruction_size() <= new_code->instruction_size());
-  }
-#endif
-  return result;
-}


 void Debug::PrepareForBreakPoints() {
@@ -1770,160 +1733,44 @@
   if (!has_break_points_) {
     Deoptimizer::DeoptimizeAll();

-    Handle<Code> lazy_compile =
- Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
-
-    // Keep the list of activated functions in a handlified list as it
-    // is used both in GC and non-GC code.
-    List<Handle<JSFunction> > active_functions(100);
-
-    {
-      // We are going to iterate heap to find all functions without
-      // debug break slots.
-      isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
-
-      // Ensure no GC in this scope as we are comparing raw pointer
-      // values and performing a heap iteration.
-      AssertNoAllocation no_allocation;
-
-      // Find all non-optimized code functions with activation frames on
-      // the stack.
- for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
-        JavaScriptFrame* frame = it.frame();
-        if (frame->function()->IsJSFunction()) {
-          JSFunction* function = JSFunction::cast(frame->function());
-          if (function->code()->kind() == Code::FUNCTION &&
-              !function->code()->has_debug_break_slots())
-            active_functions.Add(Handle<JSFunction>(function));
-        }
-      }
-      // Sort the functions on the object pointer value to prepare for
-      // the binary search below.
-      active_functions.Sort(HandleObjectPointerCompare<JSFunction>);
-
-      // Scan the heap for all non-optimized functions which has no
-      // debug break slots.
-      HeapIterator iterator;
-      HeapObject* obj = NULL;
-      while (((obj = iterator.next()) != NULL)) {
-        if (obj->IsJSFunction()) {
-          JSFunction* function = JSFunction::cast(obj);
-          if (function->shared()->allows_lazy_compilation() &&
-              function->shared()->script()->IsScript() &&
-              function->code()->kind() == Code::FUNCTION &&
-              !function->code()->has_debug_break_slots()) {
-            bool has_activation =
-                SortedListBSearch<Handle<JSFunction> >(
-                    active_functions,
-                    Handle<JSFunction>(function),
-                    HandleObjectPointerCompare<JSFunction>) != -1;
-            if (!has_activation) {
-              function->set_code(*lazy_compile);
-              function->shared()->set_code(*lazy_compile);
-            }
-          }
-        }
+    // We are going to iterate heap to find all functions without
+    // debug break slots.
+    isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
+
+    AssertNoAllocation no_allocation;
+    Builtins* builtins = isolate_->builtins();
+    Code* lazy_compile = builtins->builtin(Builtins::kLazyCompile);
+
+    // Find all non-optimized code functions with activation frames on
+    // the stack.
+    List<JSFunction*> active_functions(100);
+    for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
+      JavaScriptFrame* frame = it.frame();
+      if (frame->function()->IsJSFunction()) {
+        JSFunction* function = JSFunction::cast(frame->function());
+        if (function->code()->kind() == Code::FUNCTION)
+          active_functions.Add(function);
       }
     }
-
-    // Now the non-GC scope is left, and the sorting of the functions
-    // in active_function is not ensured any more. The code below does
-    // not rely on it.
-
-    // Now recompile all functions with activation frames and and
-    // patch the return address to run in the new compiled code.
-    for (int i = 0; i < active_functions.length(); i++) {
-      Handle<JSFunction> function = active_functions[i];
-      Handle<SharedFunctionInfo> shared(function->shared());
-      // If recompilation is not possible just skip it.
-      if (shared->is_toplevel() ||
-          !shared->allows_lazy_compilation() ||
-          shared->code()->kind() == Code::BUILTIN) {
-        continue;
-      }
-
-      // Make sure that the shared full code is compiled with debug
-      // break slots.
-      Handle<Code> current_code(function->code());
-      if (shared->code()->has_debug_break_slots()) {
-        // if the code is already recompiled to have break slots skip
-        // recompilation.
-        ASSERT(!function->code()->has_debug_break_slots());
-      } else {
-        // Try to compile the full code with debug break slots. If it
-        // fails just keep the current code.
-        ASSERT(shared->code() == *current_code);
-        ZoneScope zone_scope(isolate_, DELETE_ON_EXIT);
-        shared->set_code(*lazy_compile);
-        bool prev_force_debugger_active =
-            isolate_->debugger()->force_debugger_active();
-        isolate_->debugger()->set_force_debugger_active(true);
-        CompileFullCodeForDebugging(shared, current_code);
-        isolate_->debugger()->set_force_debugger_active(
-            prev_force_debugger_active);
-        if (!shared->is_compiled()) {
-          shared->set_code(*current_code);
-          continue;
-        }
-      }
-      Handle<Code> new_code(shared->code());
-
-      // Find the function and patch return address.
- for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
-        JavaScriptFrame* frame = it.frame();
-        // If the current frame is for this function in its
-        // non-optimized form rewrite the return address to continue
-        // in the newly compiled full code with debug break slots.
-        if (frame->function()->IsJSFunction() &&
-            frame->function() == *function &&
-            frame->LookupCode()->kind() == Code::FUNCTION) {
-          intptr_t delta = frame->pc() - current_code->instruction_start();
-          int debug_break_slot_count = 0;
-          int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT);
-          for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
-            // Check if the pc in the new code with debug break
-            // slots is before this slot.
-            RelocInfo* info = it.rinfo();
-            int debug_break_slot_bytes =
-                debug_break_slot_count * Assembler::kDebugBreakSlotLength;
-            intptr_t new_delta =
-                info->pc() -
-                new_code->instruction_start() -
-                debug_break_slot_bytes;
-            if (new_delta > delta) {
-              break;
-            }
-
-            // Passed a debug break slot in the full code with debug
-            // break slots.
-            debug_break_slot_count++;
-          }
-          int debug_break_slot_bytes =
-              debug_break_slot_count * Assembler::kDebugBreakSlotLength;
-          if (FLAG_trace_deopt) {
- PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
-                   "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
-                   "for debugging, "
- "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
-                   reinterpret_cast<intptr_t>(
-                       current_code->instruction_start()),
-                   reinterpret_cast<intptr_t>(
-                       current_code->instruction_start()) +
-                       current_code->instruction_size(),
-                   current_code->instruction_size(),
- reinterpret_cast<intptr_t>(new_code->instruction_start()), - reinterpret_cast<intptr_t>(new_code->instruction_start()) +
-                       new_code->instruction_size(),
-                   new_code->instruction_size(),
-                   reinterpret_cast<intptr_t>(frame->pc()),
- reinterpret_cast<intptr_t>(new_code->instruction_start()) +
-                       delta + debug_break_slot_bytes);
-          }
-
-          // Patch the return address to return into the code with
-          // debug break slots.
-          frame->set_pc(
- new_code->instruction_start() + delta + debug_break_slot_bytes);
+    active_functions.Sort();
+
+    // Scan the heap for all non-optimized functions which has no
+    // debug break slots.
+    HeapIterator iterator;
+    HeapObject* obj = NULL;
+    while (((obj = iterator.next()) != NULL)) {
+      if (obj->IsJSFunction()) {
+        JSFunction* function = JSFunction::cast(obj);
+        if (function->shared()->allows_lazy_compilation() &&
+            function->shared()->script()->IsScript() &&
+            function->code()->kind() == Code::FUNCTION &&
+            !function->code()->has_debug_break_slots()) {
+          bool has_activation =
+ SortedListBSearch<JSFunction*>(active_functions, function) != -1;
+          if (!has_activation) {
+            function->set_code(lazy_compile);
+            function->shared()->set_code(lazy_compile);
+          }
         }
       }
     }
@@ -2994,9 +2841,7 @@
 bool Debugger::IsDebuggerActive() {
   ScopedLock with(debugger_access_);

-  return message_handler_ != NULL ||
-      !event_listener_.is_null() ||
-      force_debugger_active_;
+  return message_handler_ != NULL || !event_listener_.is_null();
 }


=======================================
--- /branches/bleeding_edge/src/debug.h Fri Sep 30 01:39:56 2011
+++ /branches/bleeding_edge/src/debug.h Fri Sep 30 06:27:38 2011
@@ -809,15 +809,11 @@
   }

   void set_compiling_natives(bool compiling_natives) {
-    compiling_natives_ = compiling_natives;
+    Debugger::compiling_natives_ = compiling_natives;
   }
   bool compiling_natives() const { return compiling_natives_; }
   void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
   bool is_loading_debugger() const { return is_loading_debugger_; }
-  void set_force_debugger_active(bool force_debugger_active) {
-    force_debugger_active_ = force_debugger_active;
-  }
-  bool force_debugger_active() const { return force_debugger_active_; }

   bool IsDebuggerActive();

@@ -843,7 +839,6 @@
   bool compiling_natives_;  // Are we compiling natives?
   bool is_loading_debugger_;  // Are we loading the debugger?
   bool never_unload_debugger_;  // Can we unload the debugger?
- bool force_debugger_active_; // Activate debugger without event listeners.
   v8::Debug::MessageHandler2 message_handler_;
   bool debugger_unload_pending_;  // Was message handler cleared?
   v8::Debug::HostDispatchHandler host_dispatch_handler_;
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Fri Sep 30 01:39:56 2011
+++ /branches/bleeding_edge/src/full-codegen.cc Fri Sep 30 06:27:38 2011
@@ -289,12 +289,11 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
   code->set_has_debug_break_slots(
       info->isolate()->debugger()->IsDebuggerActive());
-  code->set_compiled_optimizable(info->IsOptimizable());
 #endif  // ENABLE_DEBUGGER_SUPPORT
   code->set_allow_osr_at_loop_nesting_level(0);
   code->set_stack_check_table_offset(table_offset);
   CodeGenerator::PrintCode(code, info);
-  info->SetCode(code);  // May be an empty handle.
+  info->SetCode(code);  // may be an empty handle.
 #ifdef ENABLE_GDB_JIT_INTERFACE
   if (FLAG_gdbjit && !code.is_null()) {
     GDBJITLineInfo* lineinfo =
=======================================
--- /branches/bleeding_edge/src/list-inl.h      Fri Sep 30 01:39:56 2011
+++ /branches/bleeding_edge/src/list-inl.h      Fri Sep 30 06:27:38 2011
@@ -216,11 +216,11 @@
     int mid = (low + high) / 2;
     T mid_elem = list[mid];

-    if (cmp(&mid_elem, &elem) > 0) {
+    if (mid_elem > elem) {
       high = mid - 1;
       continue;
     }
-    if (cmp(&mid_elem, &elem) < 0) {
+    if (mid_elem < elem) {
       low = mid + 1;
       continue;
     }
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Fri Sep 30 06:03:48 2011
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Sep 30 06:27:38 2011
@@ -2994,21 +2994,6 @@
   flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
 }
-
-
-bool Code::is_compiled_optimizable() {
-  ASSERT(kind() == FUNCTION);
-  byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
-  return FullCodeFlagsIsCompiledOptimizable::decode(flags);
-}
-
-
-void Code::set_compiled_optimizable(bool value) {
-  ASSERT(kind() == FUNCTION);
-  byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
-  flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
-  WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
-}


 int Code::allow_osr_at_loop_nesting_level() {
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Sep 30 06:03:48 2011
+++ /branches/bleeding_edge/src/objects.h       Fri Sep 30 06:27:38 2011
@@ -3677,11 +3677,6 @@
   inline bool has_debug_break_slots();
   inline void set_has_debug_break_slots(bool value);

-  // [compiled_with_optimizing]: For FUNCTION kind, tells if it has
-  // been compiled with IsOptimizing set to true.
-  inline bool is_compiled_optimizable();
-  inline void set_compiled_optimizable(bool value);
-
   // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
   // how long the function has been marked for OSR and therefore which
   // level of loop nesting we are willing to do on-stack replacement
@@ -3877,7 +3872,6 @@
   class FullCodeFlagsHasDeoptimizationSupportField:
       public BitField<bool, 0, 1> {};  // NOLINT
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
-  class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};

   static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;

=======================================
--- /branches/bleeding_edge/src/utils.h Fri Sep 30 01:39:56 2011
+++ /branches/bleeding_edge/src/utils.h Fri Sep 30 06:27:38 2011
@@ -141,16 +141,6 @@
 static int PointerValueCompare(const T* a, const T* b) {
   return Compare<T>(*a, *b);
 }
-
-
-// Compare function to compare the object pointer value of two
-// handlified objects. The handles are passed as pointers to the
-// handles.
-template<typename T> class Handle;  // Forward declaration.
-template <typename T>
-static int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
-  return Compare<T*>(*(*a), *(*b));
-}


 // Returns the smallest power of two which is >= x. If you pass in a

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to